《从零开始NetDevOps》是本人9年多的NetDevOps实战总结的一本书(且称之为书,通过公众号连载的方式,集结成册,希望有天能以实体书的方式和大家相见)。
本系列文章会连载于“NetDevOps加油站”公众号,欢迎大家点赞关注
加读者群请关注公众号回复“加群”。
10.2.3 实战:对若干 IP 批量 ping 检测使用情况
在实际运维中,我们有时候会有这种需求,对若干分配出去的 IP 进行 ping 检测,以便了解其是否在使用。我们的表格只有一个页签,表格只有一栏ip 地址,形如表 10-1。
ip |
192.168.137.1 |
192.168.137.2 |
192.168.137.3 |
表 10-1 批量 ping 脚本执行所需的记录 IP 地址的表格文件
我们的思路是读取表格,然后对每个 IP 地址使用 ping3 进行 ping 检测。对每个 IP 进行 ping 检测的时候,为了提高效率,我们在此使用多线程的并发技术,因为 ping 操作是占用 I/O 的一种行为,比较适合使用多线程。这里我们用到的是 Python 内置的 threading 模块,用它的 Thread 类创建一个线程对象,然后执行这个线程,这个线程对象的创建有两部分,第一部分是 target,即要执行的目标函数,第二部分是 args 即参数列表,执行的时候就会将 args 传入到 target 指向的函数。
我们先编写一个 single_ping 的函数,主要完成单独的 IP 地址的 ping 操作,创建多线程去执行这个函数。由于多线程每个线程执行结束的顺序是不受我们控制的,所以我们将 ping 结果放到一个字典变量中 ping_results,在执行开始的时候传入,每次执行的时候各个线程只更新自己 IP 地址的执行结果即可,这样也不会冲突。
然后编写一个 batch_ping 的函数,读取表格中的 IP 地址,循环创建每个 IP 地址的 ping 的线程。最后再按照原始表格中的顺序写入一个新的表格。
按照以上思路,我们编写的代码结果如下:
import threading
import pandas as pd
import ping3
def single_ping(ip, timeout, ping_results):
"""
ping 一个单独的IP地址
:param ip: 要ping的IP地址
:param timeout: ping的超时时间
:param ping_results: 所有IPping的结果,字典格式,key是IP,value是ping的结果。
"""
ping_time = ping3.ping(ip, timeout=timeout)
ping_results[ip] = ping_time
def batch_ping(file='ping.xlsx', result_file='ping_result.xlsx', timeout=4):
"""
从文件中读取待ping的列表,然后使用多线程批量去ping,结果再到一个表格文件中
:param file: 待ping的表格文件
:param timeout: 超时时间
"""
# 通过pandas读取ip列表
df = pd.read_excel(file)
ip_items = df.to_dict(orient='records')
ip_list = []
# 将字典的列表转换为字符串的列表
for i in ip_items:
ip_list.append(i['ip'])
# 用于存储ping结果的字典
ping_results = {}
# 使用多线程进行批量的ping操作
threads = []
# 循环读取IP
for ip in ip_list:
# 将每个IP地址传、超时时间和存放结果的字典,通过多线程方式传给目标函数,创建一个线程
t = threading.Thread(target=single_ping, args=(ip, timeout, ping_results))
# 线程追加到线程池
threads.append(t)
# 启动此线程任务
t.start()
# 阻塞多线程任务,即当所有的线程执行完成后再继续主程序的余下部分代码
for t in threads:
t.join()
# 将ping的结果再写会到原来的字典列表中去
# 以从表格中读取到的字典列表作为数据源,以保证顺序一致
for i in ip_items:
# 根据 IP 地址获取其结果
item_ping_result = ping_results[i['ip']]
# 对情况进行判断,以文字的方式编写结果
if item_ping_result is None:
i['result'] = '超时失败'
elif item_ping_result is False:
i['result'] = '域名解析失败'
else:
i['result'] = '成功'
# 极简表格操作法,写入表格
new_df = pd.DataFrame(ip_items)
new_df.to_excel(result_file, index=False, columns=['ip', 'result'])
if __name__ == '__main__':
batch_ping()
脚本运行结果是生成一个表格文件,其内容表 10-2。
ip | result |
192.168.137.1 | 成功 |
192.168.137.2 | 超时失败 |
192.168.137.3 | 超时失败 |
192.168.137.4 | 超时失败 |
192.168.137.5 | 超时失败 |
192.168.137.6 | 超时失败 |
192.168.137.7 | 超时失败 |
192.168.137.8 | 超时失败 |
192.168.137.9 | 超时失败 |
192.168.137.10 | 超时失败 |
192.168.137.11 | 超时失败 |
192.168.137.12 | 超时失败 |
192.168.137.13 | 超时失败 |
192.168.137.14 | 超时失败 |
表 10-2 批量 ping 脚本执行生成的表格文件
基于这段代码,我们再结合 netaddr 也可以编写一个对指定网段的批量 ping 的操作,将网段的使用情况做一个总结分析,比如查看 IP 地址的使用百分比,仍可以分配的 IP 地址等等。甚至可以和 Django、 netaddr 相结合,编写一个 IPAM (IP 地址管理系统),记录分配出去的 IP 地址,查看 IP 的实际使用情况等等。
欢迎按需加入我的读者群,关注NetDevOps公众号,回复加群即可获取我的微信,备注公司和城市!
读者二群虚位以待~