您的位置:首页 > 编程语言 > Java开发

对Ansible二次开发来检查服务器的Java程序占用端口数量

2016-01-11 14:08 549 查看
一 应用场景描述
有这个么一个需求:对很多台服务器的Java程序所占用的端口数量与正常的值进行对比确认。
可以使用如下命令得到结果:
netstat -tulnp|grep java|wc -l
但是服务器很多,每台手动去执行这条命令是不现实的。于是想到使用Ansible批量去执行,Ansible使用paramiko去ssh登录服务器执行命令,并使用mutilprocessing实现多进程ssh登录。

二 代码实现
如果直接使用Ansible去执行,不作任何处理的话。执行情况是这样的:
123456789101112# ansible -i qa_servers.txt all --private-key=/root/.ssh/id_rsa -m shell -a "netstat -tulnp|grep java|wc -l"172.30.25.71 | success | rc=0 >>3 172.30.25.179 | success | rc=0 >>19 172.30.25.180 | success | rc=0 >>86 172.30.25.181 | success | rc=0 >>82
ansible就是Ansible命令执行的命令, -i 单独指定hosts文件 --private-key指定ssh私钥路径 -m指定需要调用的模块,这里调用shell模块
-a 指定给模块传递的参数,这里既是要执行的命令

这里出现了几个问题:
a.每台服务器上的正常Java端口数量不同,并且需要和正常的值进行比对和确认,最好可以打印输出结果
b.在命令行直接调用ansible虽然对每台服务器都执行了命令但是输出结果很不规范,需要进一步处理。

Ansible本来就是Python开发的,安装完Ansible后所有的代码都位于/usr/lib/python2.6/site-packages/ansible/目录下,所以可以当作阅读正常python代码来查看Ansible源代码。
再通过查看Ansible官网的代码示例得知Ansible执行命令都是通过
/usr/lib/python2.6/site-packages/ansible/runner/__init__.py 代码中的Runner类的run函数去执行
所以想要对Ansible的输出结果进一步处理,首先要获取Ansible调用命令执行的详细信息。

完整代码如下:
12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849import ansible.runnerfrom ansible.color import stringc host_list='qa_servers.txt'private_key_file='/root/.ssh/id_rsa'pattern='*'forks=10timeout=30module_name='shell'# construct the ansible runner and execute on all hostsresults = ansible.runner.Runner(host_list=host_list,private_key_file=private_key_file,pattern=pattern,forks=forks,timeout=timeout,module_name=module_name,module_args=module_args ).run()#print resultsif results is None: print "No hosts found" sys.exit(1) print stringc("+-------------------+----------------------+-------------+-----------+--------+",color='cyan')print stringc("| HOST | HOSTNAME | CHICKED NUM | RIGHT NUM | STATUS |",color='cyan')print stringc("+-------------------+----------------------+-------------+-----------+--------+",color='cyan')for (hostname, result) in results['contacted'].items(): if not 'failed' in result: num_default=int(subprocess.Popen(''' awk '/%s/{print $3}' %s|sed -n 's/#//p' ''' %(hostname,host_list),shell=True,stdout=subprocess.PIPE).communicate()[0].split('\n')[0]) num=int(result['stdout'].split('\n')[0]) host_name=result['stdout'].split('\n')[1] if num==num_default: status=stringc('PASS',color='green') else: status=stringc('WARN',color='red') print stringc("| %-17s | %-20s | %-11d | %-9d | %-12s ",color='cyan') %(hostname,host_name,num,num_default,status) + stringc("|",color='cyan') print stringc("+-------------------+----------------------+-------------+-----------+--------+",color='cyan')# print "%s >>> %s" % (hostname, result['stdout']) #print "FAILED *******"#for (hostname, result) in results['contacted'].items():# if 'failed' in result:# print "%s >>> %s" % (hostname, result['msg']) #print "DOWN *********"#for (hostname, result) in results['dark'].items():# print "%s >>> %s" % (hostname, result)
qa_servers.txt的内容如下:
123456172.30.25.71 #testt #3172.30.25.179 #testttttttt179 #30172.30.25.180 #testttttttt180 #45172.30.25.181 #testttttttt181 #55172.30.25.172 #test #68172.30.25.173 #test #7
第一列是需要执行命令的主机IP或者主机名,第二列是主机名,第三列就是正常的Java程序占用端口数量。第二列和第三列必须要注释掉。Ansible识别主机时只识别第一列。
执行代码的结果如下:
1234567891011+-------------------+----------------------+-------------+-----------+--------+| HOST | HOSTNAME | CHICKED NUM | RIGHT NUM | STATUS |+-------------------+----------------------+-------------+-----------+--------+| 172.30.25.180 | testtesttesttt | 86 | 45 | WARN |+-------------------+----------------------+-------------+-----------+--------+| 172.30.25.181 | testttttttt181 | 82 | 55 | WARN |+-------------------+----------------------+-------------+-----------+--------+| 172.30.25.179 | testttttttt179 | 19 | 30 | WARN |+-------------------+----------------------+-------------+-----------+--------+| 172.30.25.71 | testt | 3 | 3 | PASS |+-------------------+----------------------+-------------+-----------+--------+
代码中要点:
a.直接使用Ansible的代码进行模块调用。
b.使用Ansible的color.py对输出结果进行颜色处理,PASS是绿色显示,WARN是红色显示。这里的color.py很有启示作用,如果自己以后想要对输出进行颜色处理可以直接参照这里的代码
12345678910111213141516171819codeCodes = { 'black': '0;30', 'bright gray': '0;37', 'blue': '0;34', 'white': '1;37', 'green': '0;32', 'bright blue': '1;34', 'cyan': '0;36', 'bright green': '1;32', 'red': '0;31', 'bright cyan': '1;36', 'purple': '0;35', 'bright red': '1;31', 'yellow': '0;33', 'bright purple': '1;35', 'dark gray': '1;30', 'bright yellow': '1;33', 'normal': '0'} def stringc(text, color): """String in color.""" if ANSIBLE_COLOR: return "\033["+codeCodes[color]+"m"+text+"\033[0m" else: return text
c.使用python的subprocess模块调用shell命令

参考资料:
http://docs.ansible.com/ansible/developing_api.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: