《从零开始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公众号,回复加群即可获取我的微信,备注公司和城市!

读者二群虚位以待~