Sổ tay kỹ thuật

Netmiko và Scrapli - chọn thư viện SSH

concept#python#netmiko#scrapli#ssh· cập nhật 2026-11-06

Dùng khi cần chọn thư viện Python để chạy lệnh qua SSH/CLI trên IOS XR và Junos, kèm ví dụ show và đẩy config với commit.

Sửa trang này
Mục lục

Netmiko và Scrapli đều là thư viện "screen scraping": mở phiên SSH tương tác, gửi lệnh CLI, đợi prompt rồi trả về text. Dùng khi thiết bị không có (hoặc bạn không muốn dùng) API có cấu trúc như NETCONF/gNMI. Cả hai lo phần khó: nhận diện prompt, tắt phân trang, vào/ra config mode.

Cách hoạt động

flowchart LR A["Script Python"] --> B{"Thư viện"} B -->|"Netmiko"| C["Paramiko"] B -->|"Scrapli"| D["system (OpenSSH) / paramiko / ssh2 / asyncssh"] C --> E[("Router")] D --> E E -->|"text output"| F["TextFSM / TTP / Genie"] F --> G["dict / list"]

So sánh

Tiêu chí Netmiko Scrapli
Tác giả Kirk Byers Carl Montanari
Transport SSH Paramiko Chọn được: system (mặc định, gọi binary OpenSSH), paramiko, ssh2, asyncssh, telnet, asynctelnet
Số platform Rất nhiều (hàng trăm device_type) 5 core: cisco_iosxe, cisco_iosxr, cisco_nxos, arista_eos, juniper_junos; thêm qua scrapli_community
Async Không (dùng thread để chạy song song) Có AsyncScrapli với asyncssh / asynctelnet
Tốc độ Đủ dùng, chậm hơn do chờ theo delay Nhanh hơn, đọc prompt theo pattern thay vì sleep
Dùng ~/.ssh/config (ProxyJump) Hỗ trợ qua ssh_config_file Transport system dùng OpenSSH nên ăn ~/.ssh/config tự nhiên
Parse output use_textfsm=True, use_ttp, use_genie response.textfsm_parse_output(), ttp_parse_output(), genie_parse_output()
Commit IOS XR / Junos Có method commit() Gửi commit như một lệnh trong send_configs
Hệ sinh thái Nền của Nornir-netmiko, NAPALM (một số driver), nhiều script cũ scrapli_netconf, scrapli_cfg (config replace/diff), nornir_scrapli

Ví dụ ngắn

Netmiko

nm_xr.py
import os
from netmiko import ConnectHandler
 
dev = {
    "device_type": "cisco_xr",          # Junos: "juniper_junos"
    "host": "198.51.100.11",
    "username": os.environ["NET_USER"],
    "password": os.environ["NET_PASS"],
}
 
with ConnectHandler(**dev) as conn:
    print(conn.send_command("show ipv4 interface brief"))
 
    conn.send_config_set(
        ["interface GigabitEthernet0/0/0/1", "description to-pe2-hcm"],
        exit_config_mode=False,
    )
    conn.commit(comment="CHG-1234")     # Junos: conn.commit(confirm=True, confirm_delay=5) rồi conn.commit()
    conn.exit_config_mode()

Scrapli

sc_xr.py
import os
from scrapli import Scrapli
 
dev = {
    "host": "198.51.100.11",
    "auth_username": os.environ["NET_USER"],
    "auth_password": os.environ["NET_PASS"],
    "auth_strict_key": False,           # lab; production nên kiểm tra host key
    "platform": "cisco_iosxr",          # Junos: "juniper_junos"
}
 
with Scrapli(**dev) as conn:
    r = conn.send_command("show ipv4 interface brief")
    print(r.result, r.elapsed_time)
 
    r = conn.send_configs([
        "interface GigabitEthernet0/0/0/1",
        "description to-pe2-hcm",
        "commit comment CHG-1234",
    ])
    if r.failed:
        print("Có lệnh lỗi:", [x.channel_input for x in r if x.failed])

Với IOS XR và Junos, nếu thoát config mode khi còn thay đổi chưa commit, thiết bị sẽ hỏi lại (XR: Uncommitted changes found, commit them before exiting(yes/no/cancel)?). Luôn commit hoặc abort/rollback 0 trước khi thoát để script không treo ở prompt đó.

Khi nào dùng

Tình huống Chọn
Script nhỏ, đội đã quen, nhiều vendor lạ (switch cũ, firewall, OLT...) Netmiko
Cần chạy song song hàng trăm thiết bị, muốn asyncio Scrapli (AsyncScrapli)
Phải đi qua jumphost phức tạp theo ~/.ssh/config Scrapli transport system
Cần config replace có diff cho XR/Junos scrapli_cfg, hoặc tốt hơn là NETCONF / PyEZ
Đã dùng Ansible Không cần cả hai: network_cli của Ansible đã lo SSH
Cần dữ liệu có cấu trúc, ổn định giữa các release Bỏ screen scraping, dùng NETCONF hoặc gNMI

Tham khảo