一文分享Python自動(dòng)化巡檢腳本
一、自動(dòng)化巡檢腳本:從 3 小時(shí)到 3 分鐘
我們需要什么
一個(gè)腳本,能做到:
- 讀取設(shè)備清單(IP、廠商、登錄憑據(jù))
- 逐臺(tái)登錄,執(zhí)行預(yù)設(shè)的巡檢命令
- 收集結(jié)果,按設(shè)備整理
- 生成一份 Excel 報(bào)告,異常項(xiàng)自動(dòng)標(biāo)紅
技術(shù)棧:Netmiko + 多線程 + openpyxl
第一步:設(shè)備清單
創(chuàng)建一個(gè) Python 文件,把設(shè)備信息寫進(jìn)去。設(shè)備少可直接硬編碼,多了可換成 CSV 讀取。
devices = [
{"host": "10.1.1.1", "device_type": "cisco_ios"},
{"host": "10.1.1.2", "device_type": "huawei"},
{"host": "10.1.2.1", "device_type": "cisco_ios"},
# 把你的設(shè)備全部加進(jìn)來(lái)
]
CREDENTIALS = {
"username": "admin",
"password": "your_password",
}
第二步:定義巡檢命令
不同廠商命令不一樣,用一個(gè)字典來(lái)做映射。你可以根據(jù)環(huán)境自由增減。
CHECK_COMMANDS = {
"cisco_ios": [
("show version | include Version", "軟件版本"),
("show ip interface brief", "接口狀態(tài)"),
("show processes cpu sorted | exclude 0.00%", "CPU占用"),
("show memory statistics", "內(nèi)存使用"),
("show logging | include %", "異常日志"),
("show ip route summary", "路由表概要"),
],
"huawei": [
("display version | include VRP", "軟件版本"),
("display ip interface brief", "接口狀態(tài)"),
("display cpu-usage", "CPU占用"),
("display memory-usage", "內(nèi)存使用"),
("display logbuffer | include Error", "異常日志"),
("display ip routing-table statistics", "路由表概要"),
],
}
第三步:并發(fā)巡檢(核心)
一臺(tái)一臺(tái)串行太慢,用線程池并發(fā)。30 臺(tái)設(shè)備,并發(fā) 10 線程,3 分鐘全部跑完。
from concurrent.futures import ThreadPoolExecutor, as_completed
from netmiko import ConnectHandler
from datetime import datetime
MAX_WORKERS = 10 # 同時(shí)連接 10 臺(tái)設(shè)備
def inspect_device(dev):
"""巡檢單臺(tái)設(shè)備,返回結(jié)果字典"""
result = {
"設(shè)備": dev["host"],
"廠商": dev["device_type"],
"巡檢時(shí)間": datetime.now().strftime("%Y-%m-%d %H:%M:%S"),
"狀態(tài)": "成功",
}
# 合并憑據(jù)
login = {**dev, **CREDENTIALS}
try:
with ConnectHandler(**login) as conn:
commands = CHECK_COMMANDS.get(dev["device_type"], [])
for cmd, name in commands:
try:
output = conn.send_command(cmd, read_timeout=20)
result[name] = output.strip()
except Exception as e:
result[name] = f"[執(zhí)行失敗] {e}"
except Exception as e:
result["狀態(tài)"] = "連接失敗"
result["錯(cuò)誤信息"] = str(e)
return result
# 并發(fā)執(zhí)行
reports = []
with ThreadPoolExecutor(max_workers=MAX_WORKERS) as pool:
futures = {pool.submit(inspect_device, d): d for d in devices}
for f in as_completed(futures):
reports.append(f.result())
print(f"巡檢完成:共 {len(reports)} 臺(tái)設(shè)備")
第四步:生成 Excel 報(bào)告
拿到數(shù)據(jù)只是第一步,還得讓老板看得懂。生成帶顏色標(biāo)注的 Excel,異常項(xiàng)自動(dòng)標(biāo)紅。
import openpyxl
from openpyxl.styles import Font, PatternFill, Alignment
wb = openpyxl.Workbook()
ws = wb.active
ws.title = f"設(shè)備巡檢報(bào)告_{datetime.now():%Y%m%d}"
# 表頭
headers = ["設(shè)備", "廠商", "狀態(tài)", "軟件版本", "接口狀態(tài)",
"CPU占用", "內(nèi)存使用", "異常日志", "路由表概要"]
header_fill = PatternFill(start_color="1F4E79", end_color="1F4E79",
fill_type="solid")
header_font = Font(color="FFFFFF", bold=True, size=11)
for col, h in enumerate(headers, 1):
cell = ws.cell(row=1, column=col, value=h)
cell.fill = header_fill
cell.font = header_font
cell.alignment = Alignment(horizontal="center")
# 異常標(biāo)記
red_fill = PatternFill(start_color="FFC7CE", end_color="FFC7CE",
fill_type="solid")
red_font = Font(color="9C0006")
# 寫入數(shù)據(jù)
for row, report in enumerate(reports, 2):
for col, key in enumerate(headers, 1):
value = report.get(key, "")
ws.cell(row=row, column=col, value=value)
# 包含異常關(guān)鍵詞則標(biāo)紅
if isinstance(value, str) and any(
kw in value.lower()
for kw in ["down", "error", "fail", "失敗"]
):
ws.cell(row=row, column=col).fill = red_fill
ws.cell(row=row, column=col).font = red_font
# 調(diào)整列寬
for col in ws.columns:
ws.column_dimensions[col[0].column_letter].width = 22
filename = f"巡檢報(bào)告_{datetime.now():%Y%m%d}.xlsx"
wb.save(filename)
運(yùn)行效果
巡檢完成:共 30 臺(tái)設(shè)備
報(bào)告已生成:巡檢報(bào)告_20260521.xlsx
打開 Excel,所有設(shè)備一目了然。有異常的自動(dòng)標(biāo)紅,發(fā)給領(lǐng)導(dǎo)比你手動(dòng)填的表格專業(yè)十倍。
進(jìn)階方向
這個(gè)腳本只是一個(gè)起點(diǎn)。你可以在此基礎(chǔ)上:
- 接飛書/釘釘/企微機(jī)器人:異常設(shè)備自動(dòng)推送告警
- 接數(shù)據(jù)庫(kù):每次巡檢結(jié)果入庫(kù),做歷史趨勢(shì)對(duì)比
- 定時(shí)運(yùn)行:crontab 每天 6 點(diǎn)跑一次,早上到公司直接看報(bào)告
二、會(huì)用庫(kù)的網(wǎng)工,一天干別人一周的活
很多網(wǎng)工學(xué) Python 的瓶頸不在語(yǔ)法,在“不知道有哪些好用的庫(kù)”。網(wǎng)絡(luò)自動(dòng)化領(lǐng)域已經(jīng)有一套成熟的工具鏈,這篇幫你一次性搞清楚。
第一把刀:Netmiko —— 網(wǎng)絡(luò)設(shè)備的瑞士軍刀
如果你只能學(xué)一個(gè)庫(kù),就學(xué) Netmiko。它是 Paramiko 的上層封裝,專門為網(wǎng)絡(luò)設(shè)備做 SSH 連接優(yōu)化,支持思科、華為、H3C、Juniper 等幾十個(gè)廠商。
from netmiko import ConnectHandler
dev = {
"device_type": "huawei_vrp",
"host": "10.1.1.1",
"username": "admin",
"password": "pass",
}
try:
with ConnectHandler(**dev) as conn:
print("===== 設(shè)備版本信息 =====")
print(conn.send_command("display version"))
except Exception as e:
print("連接失敗:", e)
Netmiko 幫你自動(dòng)處理廠商差異——思科 enable 模式,華為 system-view,它都自動(dòng)完成。
適用場(chǎng)景:日常登錄設(shè)備執(zhí)行命令、配置備份、批量巡檢。
第二把刀:NAPALM —— 廠商無(wú)關(guān)的網(wǎng)絡(luò)抽象
Netmiko 的局限是命令廠商相關(guān)。思科 show ip interface brief,華為 display ip interface brief。跨廠商腳本要寫一堆 if-else。NAPALM 提供統(tǒng)一 API,換廠商不改代碼邏輯。
from napalm import get_network_driver
driver = get_network_driver("ios")
device_ip = "10.1.1.1"
username = "admin"
password = "pass"
try:
with driver(device_ip, username, password, timeout=30) as dev:
facts = dev.get_facts()
print("主機(jī)名:", facts["hostname"])
print("型號(hào):", facts["model"])
print("版本:", facts["os_version"])
interfaces = dev.get_interfaces()
print("\n接口數(shù)量:", len(interfaces))
dev.discard_config()
except Exception as e:
print("連接/執(zhí)行失敗:", str(e))
殺手功能 compare_config():自動(dòng)比對(duì)當(dāng)前配置和待下發(fā)配置,只顯示差異,變更窗口神器。
適用場(chǎng)景:多廠商環(huán)境、配置比對(duì)、BGP/OSPF 狀態(tài)監(jiān)控。
第三把刀:ntc-templates —— 把 show 輸出變成結(jié)構(gòu)化數(shù)據(jù)
我們每天看這樣的輸出:
Interface IP-Address OK? Method Status
GigabitEthernet0/0 10.1.1.1 YES NVRAM up
GigabitEthernet0/1 unassigned YES NVRAM down
想在腳本里拿到“哪個(gè)接口是 down 的”,以前得寫正則解析。ntc-templates 說(shuō):不用了。
from netmiko import ConnectHandler
device = {
"device_type": "cisco_ios",
"host": "10.1.1.1",
"username": "admin",
"password": "pass"
}
with ConnectHandler(**device) as conn:
output = conn.send_command("show ip interface brief", use_textfsm=True)
for intf in output:
print(intf["intf"], intf["status"])
use_textfsm=True 背后就是 ntc-templates 在干活,內(nèi)置上百個(gè)廠商命令解析模板,輸出直接變成字典列表。
適用場(chǎng)景:任何需要結(jié)構(gòu)化解析 CLI 輸出的場(chǎng)景。
第四把刀:TextFSM —— 自定義解析,適配非標(biāo)設(shè)備
ntc-templates 覆蓋不了的非標(biāo)輸出、工控設(shè)備、安全設(shè)備,用 TextFSM 自己寫模板。
模板文件 show_int.template:
Value INTF (\S+)
Value IPADDR (\S+)
Value STATUS (up|down)
Value PROTO (up|down)
Start
^${INTF}\s+${IPADDR}\s+${STATUS}\s+${PROTO} -> Record
解析代碼:
import textfsm
output = """Vlan1 192.168.1.1 up up
Gigabit0/1 unassigned down down"""
with open("show_int.template") as tmpl:
parser = textfsm.TextFSM(tmpl)
result = parser.ParseText(output)
print(result)
寫一次模板,永久復(fù)用。
適用場(chǎng)景:非標(biāo)設(shè)備、特殊命令輸出、工控/安全設(shè)備。
第五把刀:Paramiko —— 最靈活的底層
前面四個(gè)庫(kù)底層都是 Paramiko。一般情況下不需要直接用,但跳板機(jī)、交互式會(huì)話、特殊認(rèn)證非它不可。
import paramiko
import time
ip = "10.1.1.1"
username = "admin"
password = "pass"
try:
ssh = paramiko.SSHClient()
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect(hostname=ip, username=username, password=password, port=22, timeout=10)
# 華為等設(shè)備必須用交互式 shell
shell = ssh.invoke_shell()
time.sleep(1)
shell.send("display version\n")
time.sleep(2)
output = shell.recv(65535).decode("utf-8")
print(output)
ssh.close()
except Exception as e:
print(f"連接失?。簕str(e)}")
適用場(chǎng)景:跳板機(jī)環(huán)境、復(fù)雜交互、密鑰+密碼雙因素認(rèn)證。
選型速查
| 你的需求 | 用哪個(gè)庫(kù) |
|---|---|
| 剛?cè)腴T,想連設(shè)備 | Netmiko |
| 多廠商,想統(tǒng)一接口 | NAPALM |
| 想看結(jié)構(gòu)化數(shù)據(jù) | ntc-templates + Netmiko |
| 非標(biāo)設(shè)備,需自定義解析 | TextFSM |
| 跳板機(jī) / 特殊認(rèn)證 | Paramiko |
大部分場(chǎng)景,Netmiko + ntc-templates 就夠了。等你遇到多廠商環(huán)境再加 NAPALM。
總結(jié)
手工巡檢和一個(gè)個(gè)敲命令的日子該翻篇了。一個(gè)腳本加上這幾把“刀”,能把你從重復(fù)勞動(dòng)里解放出來(lái),讓你有更多時(shí)間鉆研架構(gòu)和優(yōu)化。如果你的巡檢腳本跑起來(lái)了,或者還有特殊場(chǎng)景不知道怎么適配,歡迎留言交流。轉(zhuǎn)發(fā)給還在手工巡檢的同事,大家一起提效。
到此這篇關(guān)于一文分享Python自動(dòng)化巡檢腳本的文章就介紹到這了,更多相關(guān)Python自動(dòng)化巡檢內(nèi)容請(qǐng)搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
python爬取淘寶商品詳情頁(yè)數(shù)據(jù)
這篇文章主要為大家詳細(xì)介紹了python爬取淘寶商品詳情頁(yè)數(shù)據(jù)的相關(guān)資料,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-02-02
一文詳解Python中常用的初等函數(shù)(內(nèi)置函數(shù))
初等函數(shù)是由基本初等函數(shù)經(jīng)過有限次的四則運(yùn)算和復(fù)合運(yùn)算所得到的函數(shù),這篇文章主要介紹了Python中常用初等函數(shù)(內(nèi)置函數(shù))的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下2025-06-06
unittest+coverage單元測(cè)試代碼覆蓋操作實(shí)例詳解
這篇文章主要為大家詳細(xì)介紹了unittest+coverage單元測(cè)試代碼覆蓋操作的實(shí)例,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-04-04
利用Python高效處理Excel數(shù)據(jù)的實(shí)踐指南
在當(dāng)今的數(shù)據(jù)驅(qū)動(dòng)時(shí)代,Python已成為數(shù)據(jù)科學(xué)家和分析師不可或缺的工具,本文將深入探討Python讀取Excel文件的方法,希望可以幫助大家輕松駕馭各種復(fù)雜的Excel數(shù)據(jù)2025-09-09
Python3+django2.0+apache2+ubuntu14部署網(wǎng)站上線的方法
這篇文章主要介紹了Python3+django2.0+apache2+ubuntu14部署網(wǎng)站上線的方法,小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,也給大家做個(gè)參考。一起跟隨小編過來(lái)看看吧2018-07-07
Anaconda+pycharm安裝及環(huán)境配置全過程
在使用pyCharm進(jìn)行開發(fā)時(shí),需要用到Anaconda創(chuàng)建的環(huán)境,下面這篇文章主要給大家介紹了關(guān)于Anaconda+pycharm安裝及環(huán)境配置的相關(guān)資料,文中通過實(shí)例代碼介紹的非常詳細(xì),需要的朋友可以參考下2022-09-09

