Python多线程与gevent高效批量Ping检测在线IP
本文介绍利用Python高效检测网段内在线IP的两种方案。针对设备众多、重复维护场景,分别采用threading模块实现多线程并发ping,以及gevent资源池进行异步IO处理。通过对比两种代码实现,帮助开发者快速掌握批量网络连通性检测技巧,提升运维效率。
问题描述
在某些运维场景下,需要确认多台终端是否在线,通常会使用ping命令进行连通性测试。当待检测设备数量较少时,手动操作尚可接受;但若维护设备规模庞大,手动ping将变得极其繁琐。此时,自动化脚本的价值便凸显出来。此外,由于单线程执行效率较低,难以在短时间内完成大量统计,因此引入多线程机制是必要的优化手段。
应用背景
存在多台设备需要维护,且维护周期短、重复性高;
单台设备配置多个IP地址,需频繁确认网络是否畅通;
其他需要批量确认网络连通性的场景。
问题解决
利用Python内置的threading模块实现多线程并发操作。若系统中未安装相关依赖,请通过pip install package name命令进行安装。
threading并发ping操作代码实现
该段代码源自网络(疑似stackoverflow),具体来源已不可考,但其核心价值在于提供了实用的解决方案。代码中关键位置已添加注释,用户可根据实际需求自定义IP所属网段及线程数量。从实际效果来看,这是一段相当高效的代码。
# -*- coding: utf-8 -*-
import sys
import os
import platform
import subprocess
import Queue
import threading
import ipaddress
import re
def worker_func(pingArgs, pending, done):
try:
while True:
# Get the next address to ping.
address = pending.get_nowait()
ping = subprocess.Popen(pingArgs + [address],
stdout = subprocess.PIPE,
stderr = subprocess.PIPE
)
out, error = ping.communicate()
if re.match(r".*, 0% packet loss.*", out.replace("\n", "")):
done.put(address)
# Output the result to the 'done' queue.
except Queue.Empty:
# No more addresses.
pass
finally:
# Tell the main thread that a worker is about to terminate.
done.put(None)
# The number of workers.
NUM_WORKERS = 14
plat = platform.system()
scriptDir = sys.path[0]
hosts = os.path.join(scriptDir, 'hosts.txt')
# The arguments for the 'ping', excluding the address.
if plat == "Windows":
pingArgs = ["ping", "-n", "1", "-l", "1", "-w", "100"]
elif plat == "Linux":
pingArgs = ["ping", "-c", "1", "-l", "1", "-s", "1", "-W", "1"]
else:
raise ValueError("Unknown platform")
# The queue of addresses to ping.
pending = Queue.Queue()
# The queue of results.
done = Queue.Queue()
# Create all the workers.
workers = []
for _ in range(NUM_WORKERS):
workers.append(threading.Thread(target=worker_func, args=(pingArgs, pending, done)))
# Put all the addresses into the 'pending' queue.
for ip in list(ipaddress.ip_network(u"10.69.69.0/24").hosts()):
pending.put(str(ip))
# Start all the workers.
for w in workers:
w.daemon = True
w.start()
# Print out the results as they arrive.
numTerminated = 0
while numTerminated < NUM_WORKERS:
result = done.get()
if result is None:
# A worker is about to terminate.
numTerminated += 1
else:
print result # print out the ok ip
# Wait for all the workers to terminate.
for w in workers:
w.join()
另一种思路是利用资源池概念,直接调用gevent模块提供的异步功能。
资源池代码实现
这段代码源自公司内部Python专家的作品,本人仅为此主题做了少量调整。核心观点不变:只要代码具备实用价值且能持续运行,就是正确且值得采用的方案。
# -*- coding: utf-8 -*-
from gevent import subprocess
import itertools
from gevent.pool import Pool
pool = Pool(100) # concurrent action count
ips = itertools.product((10, ), (69, ), (69, ), range(1, 255))
def get_response_time(ip):
try:
out = subprocess.check_output('ping -c 1 -W 1 {}.{}.{}.{}'.format(*ip).split())
for line in out.splitlines():
if '0% packet loss' in line:
return ip
except subprocess.CalledProcessError:
pass
return None
resps = pool.map(get_response_time, ips)
reachable_resps = filter(lambda (ip): ip != None, resps)
for ip in reachable_resps:
print ip
github目录:git@github.com:qcq/Code.git 下的子目录utils内部。
以上关于Python获取网段内ping通IP的方法即为全部内容,希望能对读者有所参考,也欢迎大家继续支持本站。
免责声明:本文内容仅供参考,不代表本站观点。转载或引用请注明出处。









