简单用python实现了一段监控主机状态的代码,有两个线程,一个线程负责执行ping,将ping的结果保存在主进程的LIST中,另一线程负责检查该结果,并在检测到主机状态变化时执行其它操作,比如发送邮件报警等。有两种情况会认为主机down了,一是当连续5个ping包都timeout时;二是在20次ping 中有10个timeout时,后者主要目的在于当主机线路出现抖动(时通时断)时也认为主机不可用了;在主机处于down状态时,连继5次ping包都正常,则将主机状态恢复为up。
目前该脚本还有些不足,threading创建多个线程后,发送给主进程的SIGINT信号都被阻塞了,所以ctrl+c不能中止程序,要直接kill掉才行,正在想法解决。
以上问题已经解决,将子线程设置为Daemon,主进程不再被子线程阻塞,可以正常接收信号。为保证主进程不退出,使用一个判断子线程是否存活的循环,子线程中增加判断全局的一个标记,如果标记为True则结束并退出,主进程收到ctrl+c的信号后,将全局的标记设置为True,子线程退出,主进程检测到线程没有存活也就退出。
在我们实际应用中,主机状态发生变化执行操作是邮件通知和修改三层交换机默认网关,两个功能也是通过python来实现的,目前代码很不整洁,待整理后放出。
脚本执行需要ping模块,到这里下载,将ping.py和以下脚本文件放到同一目录即可。
#!/usr/bin/env python
import time,threading,sys
from ping import *
import signal
ping_timeout=2
status_last=True
status_list=[ 1 for i in range(0,20) ]
dest_ip=''
tread_exit=False
def thread_exit(a,b):
global tread_exit
tread_exit=True
def ping_check(dest_addr):
global status_list
global dest_ip
global tread_exit
dest_ip=dest_addr
while not tread_exit:
print "ping %s with ..." % dest_addr ,
try:
delay = do_one(dest_addr, ping_timeout, 64)
except Exception,err:
print err
print "Network error"
time.sleep(1)
continue
if delay == None:
status_list.insert(0,0)
status_list.pop()
print "failed. (timeout within %ssec.)" % ping_timeout
else:
delay = delay * 1000
status_list.insert(0,1)
status_list.pop()
print "get ping in %0.4fms" % delay
time.sleep(1)
def check_status():
global status_list
global status_last
global dest_ip
global tread_exit
status_changed=False
status_list_copy=status_list
while not tread_exit:
if status_list_copy[:5].count(1)==5:
status_now=True
elif status_list_copy[:5].count(0)==5 or status_list_copy.count(0)==10:
status_now=False
if status_now!=status_last:
status_changed=True
else:
status_changed=False
status_last=status_now
if status_changed==True:
if status_now==False:
print dest_ip,"status to Down"
elif status_now==True:
print dest_ip,"status to Up"
#print 'now status is: ', status_now
time.sleep(0.3)
if __name__ == '__main__':
signal.signal(signal.SIGINT,thread_exit)
th_ping=threading.Thread(target=ping_check,args=("10.0.0.1",))
th_status=threading.Thread(target=check_status)
th_ping.setDaemon(True)
th_status.setDaemon(True)
th_ping.start()
th_status.start()
while th_ping.isAlive() or th_status.isAlive():
time.sleep(1)
我需要使用python实现ping功能,好像这个ping使用了socket.SOCK_RAW需要root权限的,不知道你那里是不是有这个问题?
会,也有这样的问题,我实际部署的环境都是以root用户登陆,使用screen运行
do_one这个是什么意思?
do_one 是ping 模块中提供的方法,作用是执行一次ping操作。
我的提示找不到这个呢!