Python有很多多线程的模块,好坏不一。在缺乏系统线程知识的情况下,逐一试用吧。
threading
背景:写了一个用python-nmap查找在线主机的脚本。ip地址是从dhcpd的dhcpd.leases里面用正则表达式匹配出来的。然后把ip放到alive_state函数里面查找up的主机。屏蔽了dhcpd的内容为了不泄漏公司信息。
代码:
# 查找up的ip,其实就是用nmap的ping查找
# 考虑到windows主机会屏蔽ping,所以再用windows_os_alive函数再过滤一遍
def find_alive(host):
nm = nmap.PortScanner()
nm.scan(hosts=host, arguments='-sP')
up_hosts = int(nm.scanstats()['uphosts'])
if up_hosts:
return True
else: # Windows OS blocked ping check, run check with port detection again
# to make sure know windows is alive
if windows_os_alive(host):
return True
return False
# 检测windows
def windows_os_alive(host):
nm = nmap.PortScanner()
nm.scan(hosts=host, arguments='-PN -p 135')
up_hosts = int(nm.scanstats()['uphosts'])
if up_hosts:
return True
else:
return False
# 用了Django的model来操作数据库,因为我的sql很差
def save_into_db(mac_addr, mac_timestamp, mac_ip, mac_state):
try:
mac.objects.get(mac=mac_addr)
mac.objects.filter(mac=mac_addr).update(ip_addr=mac_ip, state=mac_state,
timestamp=mac_timestamp)
except mac.DoesNotExist:
p = mac(mac=mac_addr, ip_addr=mac_ip, state=mac_state,
timestamp=mac_timestamp, serial_number=DEF_ASSET_INSTANCE)
p.save()
# 多线程的类,重点再这里吧
class handle_entries(threading.Thread):
# 初始化一下
def __init__(self, mac, mac_detail):
threading.Thread.__init__(self)
self.mac = mac
self.mac_detail = mac_detail
# 因为是用的threading,所以要自己写run,也符合这个案例的需求,因为我想同时再终端输出过程。不过多线程的情况下,输出是乱的,因为不是按序操作。
def run(self):
if (NOW - self.mac_detail['timestamp']) <= 43200: # only test alive with hosts in
# two days
if find_alive(self.mac_detail['ip']):
alive_state = 'Alive'
else:
alive_state = 'Offline'
else:
alive_state = 'Depercated'
# add alive stats into result
dhcp_result[self.mac]['state'] = alive_state
ip_tab = ' ' * (15 - len(self.mac_detail['ip']))
oneline_string = '| {} | {} | {}{} | {} |'.format(
self.mac, self.mac_detail['timestamp'], self.mac_detail['ip'], ip_tab, alive_state)
save_into_db(self.mac, self.mac_detail['timestamp'], self.mac_detail['ip'], alive_state)
print oneline_string
# print '-' * len(oneline_string)
if __name__ == '__main__':
start_time = time.time()
dhcp_result = filter_dhcp_client()
print '=' * 80
print 'Total collected: {}'.format(len(dhcp_result))
print '=' * 80
threads = [] # 先开一个空的列表来存放所有进程
for k, v in dhcp_result.items():
threads.append(handle_entries(k, v)) # 一口气把所有要查询的ip都放到进程里面
for t in threads: # 用循环一个个启动进程,其实就是run()里面的内容
t.start()
for t in threads: # 看了很多例子都说用join是为了等待进程结束。因为我这里最后要打印耗时和一些额外的信息,所以我也用join
t.join()
print '=' * 80
end_time = time.time()
print '{} find_alive threads are loaded!'.format(len(threads))
print 'Time cost: {}s'.format(end_time - start_time)
# wirte into file with json
with open('./dhcp_result.json', 'w') as f:
f.write(json.dumps(dhcp_result))