Netmiko SSH 自動化
在撰寫或審查使用 Netmiko 連線網路設備的 Python 自動化腳本時,使用此技能。保持預設路徑為唯讀;設定變更需要獨立的變更窗口、同儕審查與回退計畫。
使用時機
- 從路由器、交換器或防火牆收集
show命令輸出。 - 建立小型稽核腳本,取得介面、路由或設定證據。
- 為網路 SSH 腳本加入逾時設定與例外處理。
- 當存在 TextFSM 範本時,使用它解析命令輸出。
- 在自動化腳本接觸生產設備前進行審查。
安全預設值
- 從唯讀的
send_command()收集開始。 - 保持設備清單小而明確;不要掃描整個 IP 範圍。
- 使用環境變數、密碼管理工具或
getpass;永遠不要將憑證寫死在程式碼中。 - 設定連線與讀取逾時。
- 限制並行數量,避免老舊設備過載。
- 在
send_config_set()之前需要明確的操作者標誌。 - 在設定變更經過驗證與核准之前,不要呼叫
save_config()。
唯讀連線模式
import os
from getpass import getpass
from netmiko import ConnectHandler
from netmiko.exceptions import (
NetmikoAuthenticationException,
NetmikoTimeoutException,
ReadTimeout,
)
device = {
"device_type": "cisco_ios",
"host": "192.0.2.10",
"username": os.environ.get("NETMIKO_USERNAME") or input("使用者名稱: "),
"password": os.environ.get("NETMIKO_PASSWORD") or getpass("密碼: "),
"secret": os.environ.get("NETMIKO_ENABLE_SECRET"),
"conn_timeout": 10,
"auth_timeout": 20,
"banner_timeout": 15,
"read_timeout_override": 30,
}
try:
with ConnectHandler(**device) as conn:
if device.get("secret") and not conn.check_enable_mode():
conn.enable()
output = conn.send_command("show ip interface brief", read_timeout=30)
print(output)
except NetmikoAuthenticationException:
print("驗證失敗")
except NetmikoTimeoutException:
print("SSH 連線逾時")
except ReadTimeout:
print("命令讀取逾時")
在範例中使用文件範圍內的佔用位址。將真實設備清單保存在被忽略的本地檔案或機密管理系統中。
批次收集
from concurrent.futures import ThreadPoolExecutor, as_completed
from typing import Any
def collect_show(device: dict[str, Any], command: str) -> dict[str, Any]:
host = device["host"]
try:
with ConnectHandler(**device) as conn:
output = conn.send_command(command, read_timeout=45)
return {"host": host, "ok": True, "output": output}
except (NetmikoAuthenticationException, NetmikoTimeoutException, ReadTimeout) as exc:
return {"host": host, "ok": False, "error": type(exc).__name__}
results = []
with ThreadPoolExecutor(max_workers=8) as pool:
futures = [pool.submit(collect_show, device, "show version") for device in devices]
for future in as_completed(futures):
results.append(future.result())
保持 max_workers 較低,除非已知設備機群與 AAA 系統能處理更高的連線數量。
結構化解析
Netmiko 可以要求 TextFSM、TTP 或 Genie 解析支援的命令輸出。將解析器輸出視為最佳化手段,而非唯一的證據來源。
with ConnectHandler(**device) as conn:
parsed = conn.send_command(
"show ip interface brief",
use_textfsm=True,
raise_parsing_error=False,
read_timeout=30,
)
if isinstance(parsed, str):
print("無相符的解析器範本;儲存原始輸出以供審查")
else:
for row in parsed:
print(row)
如果解析結果影響了關鍵決策,請同時保留原始命令輸出,以便操作員檢查不一致之處。
防護式設定模式
import os
commands = [
"interface GigabitEthernet0/1",
"description CHANGE-1234 UPLINK-TO-CORE",
]
apply_changes = os.environ.get("APPLY_NETWORK_CHANGES") == "1"
if not apply_changes:
print("僅限乾執行。候選命令:")
print("\n".join(commands))
else:
with ConnectHandler(**device) as conn:
conn.enable()
before = conn.send_command("show running-config interface GigabitEthernet0/1")
output = conn.send_config_set(commands)
after = conn.send_command("show running-config interface GigabitEthernet0/1")
print(before)
print(output)
print(after)
print("在儲存啟動配置前,先驗證行為。")
儲存設定是獨立的核准步驟。在生產環境中,應包含回退程式碼片段,並在變更記錄中擷取變更前後的證據。
審查清單
- 腳本是否指定了明確的設備清單來源?
- 憑證是否未出現在原始碼、日誌與例外訊息中?
conn_timeout、auth_timeout與命令read_timeout是否已設定?- 失敗是否回報到每個設備,而不中斷整個批次?
- 腳本是否避免廣泛掃描與無限制的並行?
- 設定變更是否位於乾執行或明確的操作者標誌之後?
save_config()是否與初始推送分開,並與驗證相關聯?
反模式
- 在原始碼中寫死密碼、啟用密碼或私鑰。
- 將傳送設定命令作為預設程式碼路徑。
- 針對 CIDR 範圍執行自動化,而非經過審查的設備清單。
- 未經清理即將完整執行中的設定記錄到共享系統。
- 將解析成功視為設備狀態正確的證據。
另請參閱
- 技能:
cisco-ios-patterns - 技能:
network-config-validation - 技能:
network-interface-health