この記事は、 「ネットワーク上級編|要件定義・設計・クラウド・自動化へ進む」 の第54回です。
第6章では、Python・SSH・Ansible・API・Gitなどを使い、 ネットワーク運用を自動化・効率化する方法を学びます。
SSHによる情報取得|Pythonでネットワーク機器からshowコマンドを自動収集する
ネットワーク機器を1台ずつ開き、 showコマンドを入力して結果をコピーする作業は、 台数が増えるほど時間と確認漏れのリスクが増えます。 SSHとPythonを組み合わせれば、 複数機器へ接続して同じ情報をまとめて取得する処理を自動化できます。
たとえば、20台のネットワーク機器について OSバージョン、インターフェース状態、ルーティングテーブルを確認するとします。
手作業では、20台へ順番にSSH接続し、 コマンドを入力し、結果を保存する必要があります。
しかしPythonからSSH接続できれば、 「接続 → コマンド実行 → 結果取得 → ファイル保存」 という一連の処理をプログラムに任せられます。
この記事を読み終えるとできること
- SSHを自動化で利用する目的を説明できる
- PythonからSSH接続できる
- SSH経由でコマンドを実行できる
- コマンド結果をPythonへ取り込める
- 複数機器から情報を収集できる
- 取得結果をファイルへ保存できる
- タイムアウトや認証失敗を処理できる
- 認証情報とホストキーを安全に扱う考え方を理解できる
SSHによる情報取得とは何か
SSHによる情報取得とは、 プログラムからネットワーク機器へSSH接続し、 コマンドを実行して、その出力結果を自動的に収集することです。
ネットワークエンジニアが日常的に行う確認作業には、 SSHで実行できるものが数多くあります。
show version
show ip interface brief
show ip route
show interfaces
これらを人が1台ずつ取得する代わりに、 Pythonから機器へ接続してまとめて実行します。
SSHは「設定投入」だけでなく「情報取得」にも利用できます。
自動化を始めるときは、 いきなり設定変更を自動化するより、 まずshowコマンドなどの 読み取り処理から始める と安全に学習できます。
なぜSSHによる自動取得が必要なのか
作業時間を短縮できる
同じコマンドを数十台へ実行する作業を プログラムへ任せられます。
取得漏れを減らせる
実行するコマンドをコードで固定するため、 「この機器だけshow routeを取り忘れた」 といった漏れを減らせます。
同じ条件で比較できる
全機器へ同一コマンドを実行し、 同じ形式で保存できます。
定期取得へ発展できる
自動実行と組み合わせれば、 毎日・毎週など一定間隔で状態を保存できます。
手作業と自動取得を比較する
| 項目 | 手作業 | SSH自動取得 |
|---|---|---|
| 接続 | 1台ずつ接続 | プログラムから順番に接続 |
| コマンド実行 | 人が入力 | コードで実行 |
| 結果保存 | コピー&ペースト | 自動保存 |
| 大量機器 | 時間がかかる | 繰り返し処理が可能 |
| 取得条件 | ばらつく可能性がある | 統一しやすい |
SSH情報取得の全体像
SSHによる情報取得は、 大きく次の流れで行います。
- 接続先を決める IPアドレス、SSHポート、ユーザー名などを用意します。
- SSHセッションを確立する PythonからSSHサーバーまたはネットワーク機器へ接続します。
- コマンドを送信する showコマンドなど、必要な確認コマンドを実行します。
- 出力を取得する コマンド結果をPythonの文字列として受け取ります。
- 保存・解析する テキストファイルやCSVへ保存したり、 必要な値だけ抽出したりします。
Python環境を準備する
PythonからSSHを扱う方法はいくつかありますが、 この記事ではPythonのSSHライブラリ Paramikoを使用します。
Paramikoをインストールする
python -m pip install paramiko
インストール後、Pythonから読み込めるか確認します。
import paramiko
print(paramiko.__version__)
ネットワーク機器の操作に特化したライブラリとして Netmikoなどもあります。
ここではまず、 SSH接続そのものの仕組みを理解するために Paramikoを利用します。
1台へSSH接続する
まずは、1台のSSH接続先へ接続する最小構成を確認します。
import paramiko
host = "192.168.10.1"
username = "admin"
password = "your-password"
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(
hostname=host,
port=22,
username=username,
password=password,
timeout=10
)
print("SSH接続に成功しました")
client.close()
コードを分解して確認する
SSHClientを作成する
client = paramiko.SSHClient()
SSH接続を管理するためのオブジェクトを作成します。
ホストキーを読み込む
client.load_system_host_keys()
SSHでは、 接続先が想定した機器であるか確認するために ホストキーを利用します。
SSH接続を行う
client.connect(
hostname=host,
port=22,
username=username,
password=password,
timeout=10
)
| 引数 | 意味 |
|---|---|
hostname |
接続先IPアドレスまたはホスト名 |
port |
SSHポート。一般的には22 |
username |
SSH認証で使用するユーザー名 |
password |
パスワード認証で使用するパスワード |
timeout |
接続待ち時間 |
接続を閉じる
client.close()
処理が終了したら、 SSH接続を閉じます。
コマンドを実行して結果を取得する
SSH接続だけでは情報は取得できません。 接続後にコマンドを実行し、 その結果を読み取ります。
SSH接続先がSSHの
exec形式のコマンド実行に対応している場合は、
Paramikoのexec_command()を利用できます。
import paramiko
host = "192.168.10.1"
username = "admin"
password = "your-password"
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(
hostname=host,
username=username,
password=password,
timeout=10
)
stdin, stdout, stderr = client.exec_command("show version")
output = stdout.read().decode("utf-8")
error = stderr.read().decode("utf-8")
print(output)
if error:
print("ERROR:")
print(error)
client.close()
3つの戻り値
| 変数 | 役割 |
|---|---|
stdin |
コマンドへ入力を渡すためのストリーム |
stdout |
通常のコマンド出力 |
stderr |
エラー出力 |
SSHで取得した結果は最終的にPythonのデータとして扱える ことが重要です。
取得後は、ファイル保存、文字列検索、差分比較、 CSV化などへ発展できます。
ネットワーク機器の対話型CLIを操作する
ネットワーク機器では、 SSH接続するとCLIプロンプトが表示され、 そこへコマンドを入力する 対話型操作 が必要になる場合があります。
その場合は、
invoke_shell()
で対話型シェルを開始します。
import paramiko
import time
host = "192.168.10.1"
username = "admin"
password = "your-password"
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(
hostname=host,
username=username,
password=password,
timeout=10
)
channel = client.invoke_shell()
time.sleep(1)
if channel.recv_ready():
initial_output = channel.recv(65535).decode(
"utf-8",
errors="ignore"
)
print(initial_output)
channel.send("show version\n")
time.sleep(2)
output = ""
while channel.recv_ready():
output += channel.recv(65535).decode(
"utf-8",
errors="ignore"
)
print(output)
client.close()
ネットワーク機器ではページングに注意する
CLIでは、出力が長いと
--More--
などで表示が一時停止することがあります。
自動取得では、 ページングを無効化してからshowコマンドを実行する方法が一般的です。
channel.send("terminal length 0\n")
time.sleep(1)
channel.send("show version\n")
time.sleep(2)
CLIコマンドはベンダーやOSによって異なります。
terminal length 0はCisco IOS系の例です。
実際の環境では対象機器のCLI仕様を確認してください。
複数のshowコマンドを実行する
commands = [
"show version",
"show ip interface brief",
"show ip route"
]
for command in commands:
channel.send(command + "\n")
time.sleep(2)
output = ""
while channel.recv_ready():
output += channel.recv(65535).decode(
"utf-8",
errors="ignore"
)
print("=" * 60)
print(command)
print("=" * 60)
print(output)
複数機器から情報を取得する
SSH自動化の効果が大きくなるのは、 複数機器を対象にした場合です。
たとえば、接続先をリストとして定義します。
devices = [
{
"name": "RT01",
"host": "192.168.10.1"
},
{
"name": "RT02",
"host": "192.168.10.2"
},
{
"name": "SW01",
"host": "192.168.10.11"
}
]
これをfor文で順番に処理します。
import paramiko
import time
username = "admin"
password = "your-password"
devices = [
{"name": "RT01", "host": "192.168.10.1"},
{"name": "RT02", "host": "192.168.10.2"},
{"name": "SW01", "host": "192.168.10.11"}
]
commands = [
"show version",
"show ip interface brief"
]
for device in devices:
print(f"Connecting: {device['name']}")
client = paramiko.SSHClient()
client.load_system_host_keys()
client.connect(
hostname=device["host"],
username=username,
password=password,
timeout=10
)
channel = client.invoke_shell()
time.sleep(1)
if channel.recv_ready():
channel.recv(65535)
channel.send("terminal length 0\n")
time.sleep(1)
for command in commands:
channel.send(command + "\n")
time.sleep(2)
output = ""
while channel.recv_ready():
output += channel.recv(65535).decode(
"utf-8",
errors="ignore"
)
print(
f"\n[{device['name']}] {command}"
)
print(output)
client.close()
この時点で、人が3台へログインして 同じコマンドを入力する作業を Pythonへ置き換えられました。
ネットワーク自動化では 「1台で動く処理を作り、その後に複数台へ広げる」 のが基本です。
最初から数十台を対象にせず、 検証環境の1台で十分に確認してから対象を増やします。
取得結果をファイルへ保存する
画面へ表示するだけでは、 後から確認したり比較したりできません。
取得結果をファイルへ保存してみましょう。
filename = "RT01_show_version.txt"
with open(
filename,
"w",
encoding="utf-8"
) as f:
f.write(output)
機器名と日時をファイル名へ入れる
実務では、いつ取得した情報か分かるようにすると便利です。
from datetime import datetime
device_name = "RT01"
timestamp = datetime.now().strftime(
"%Y%m%d_%H%M%S"
)
filename = (
f"{device_name}_"
f"{timestamp}.txt"
)
with open(
filename,
"w",
encoding="utf-8"
) as f:
f.write(output)
たとえば、次のようなファイルが作成されます。
RT01_20260816_010500.txt
RT02_20260816_010507.txt
SW01_20260816_010514.txt
コマンド単位で保存する
さらに管理しやすくするなら、 機器ごと・コマンドごとに分けます。
outputs/
├── RT01/
│ ├── show_version.txt
│ ├── show_ip_interface_brief.txt
│ └── show_ip_route.txt
├── RT02/
│ ├── show_version.txt
│ ├── show_ip_interface_brief.txt
│ └── show_ip_route.txt
└── SW01/
├── show_version.txt
└── show_ip_interface_brief.txt
エラー処理を追加する
実際のネットワークでは、 すべての機器へ必ず接続できるとは限りません。
- 機器が停止している
- IPアドレスを間違えている
- SSHが許可されていない
- ユーザー名・パスワードが違う
- ACLやファイアウォールで遮断されている
- タイムアウトする
1台の失敗でプログラム全体が停止すると、 残りの機器から情報を取得できません。
そこでtryとexceptを利用します。
import paramiko
import socket
try:
client.connect(
hostname=host,
username=username,
password=password,
timeout=10
)
except paramiko.AuthenticationException:
print(
f"{host}: 認証に失敗しました"
)
except (
socket.timeout,
TimeoutError
):
print(
f"{host}: 接続がタイムアウトしました"
)
except paramiko.SSHException as e:
print(
f"{host}: SSHエラー: {e}"
)
except OSError as e:
print(
f"{host}: 接続エラー: {e}"
)
成功・失敗を記録する
大量の機器を処理するときは、 最後に結果一覧を確認できるようにします。
| 機器 | 結果 | 備考 |
|---|---|---|
| RT01 | 成功 | 3コマンド取得 |
| RT02 | 失敗 | Authentication failed |
| SW01 | 成功 | 3コマンド取得 |
| SW02 | 失敗 | Connection timeout |
自動化では 成功した処理だけでなく、失敗した処理を残す ことが重要です。
「50台中47台成功」だけではなく、 失敗した3台と理由を確認できるようにします。
認証情報とホストキーを安全に扱う
SSH自動化で特に注意したいのが、 ユーザー名・パスワード・秘密鍵などの認証情報です。
パスワードをコードへ直接書かない
避けたい例
username = "admin"
password = "NetworkPassword123"
ソースコードをGitなどへ登録すると、 パスワードまで保存される可能性があります。
環境変数から取得する例
import os
username = os.environ["SSH_USERNAME"]
password = os.environ["SSH_PASSWORD"]
さらに本格的な環境では、 パスワード管理・Secrets管理の仕組みを利用します。
ホストキーを確認する
SSHでは、 接続先サーバーや機器のホストキーを確認します。
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(
paramiko.RejectPolicy()
)
未登録のホストキーを無条件に信頼するのではなく、 想定した接続先であることを確認したうえで登録する運用を考えます。
インターネット上のサンプルでは、
AutoAddPolicy()
を指定するコードを見かけることがあります。
学習環境では便利ですが、 本番環境では未知のホストキーを自動的に受け入れる設計が 適切かを確認してください。
取得データ自体にも注意する
SSHで取得した出力には、 次のような機密情報が含まれる可能性があります。
- IPアドレス
- ホスト名
- ネットワーク構成
- ルーティング情報
- インターフェース情報
- 設定情報
- 認証関連情報
特にrunning-configなどを取得する場合は、 保存場所、アクセス権、保管期間をあらかじめ決めます。
実務でSSH情報取得を設計するときのポイント
1.最初は読み取り専用から始める
自動化を初めて導入する場合は、 showコマンドなどの参照処理から開始します。
情報取得で十分に動作確認してから、 設定変更の自動化へ進む方が安全です。
2.対象機器を明確にする
- 対象機器名
- 管理IPアドレス
- ベンダー
- OS
- SSHポート
- 実行するコマンド
特にベンダーやOSが異なる場合、 同じ目的でもコマンドが異なることがあります。
3.実行アカウントの権限を考える
情報取得だけが目的であれば、 必要以上の設定変更権限を与えないことを検討します。
4.タイムアウトを必ず設定する
応答しない機器を無制限に待つと、 1台の障害で全体処理が進まなくなる可能性があります。
5.ログを残す
- 実行開始日時
- 対象機器
- 成功・失敗
- 実行したコマンド
- エラー内容
6.SSH出力と構造化データを区別する
CLIから取得したshowコマンドの結果は、 基本的には人間が読むことを前提にしたテキストです。
そのため、 「インターフェースがupのものだけ集計したい」 といった処理では、 出力を解析する工程が必要になります。
SSHで取得できることと、 取得結果を簡単にプログラム処理できることは別です。
将来的にREST APIやJSON形式で取得できる機器では、 構造化データを利用した方が扱いやすい場合があります。
SSH情報取得でよくある失敗
Gitや共有フォルダーを経由して、 認証情報が第三者へ見える可能性があります。
長いshowコマンドの途中で出力が停止し、 情報を最後まで取得できないことがあります。
sleep(2)だけで処理すると、
出力が遅い機器では結果を取り切れない可能性があります。
実務ではプロンプト検出や受信状態などを考慮した実装が必要です。
複数機器を扱う場合は、 1台ごとにエラーを処理し、 残りの機器を継続できるようにします。
showコマンド、ページング解除、 プロンプト形式などは機器によって異なります。
まず1台の検証機で確認し、 数台、数十台と段階的に対象を増やします。
保存データにはネットワーク構成や機密情報が含まれる可能性があります。 保存場所やアクセス権を設計します。
顧客・上司への説明方法
自動化を説明するときは、 「Pythonを使います」だけではなく、 業務上の効果へ変換して説明します。
技術だけを説明した例
「PythonのParamikoを使って、 SSHでshowコマンドを取得します。」
業務効果まで説明した例
「現在は機器ごとにSSH接続して取得している状態確認情報を、 Pythonから同一条件で自動取得する仕組みに変更します。 これにより、定期点検の作業時間を削減し、 コマンド取得漏れを防ぎやすくします。」
設計レビューで説明するポイント
- 何を自動化するのか
- 対象機器は何台か
- どのアカウントで実行するのか
- 設定変更を行うのか、情報取得だけなのか
- 失敗時にどう記録するのか
- 認証情報をどのように保護するのか
- 取得データをどこへ保存するのか
SSH自動化で使う英語表現
| 英語 | 意味 | 実務での使われ方 |
|---|---|---|
| SSH connection | SSH接続 | Establish an SSH connection. |
| authentication | 認証 | SSH authentication failed. |
| credentials | 認証情報 | Do not store credentials in source code. |
| host key | ホストキー | Verify the SSH host key. |
| command output | コマンド出力 | Save the command output to a file. |
| timeout | タイムアウト | The SSH connection timed out. |
| interactive shell | 対話型シェル | Open an interactive shell. |
| exception handling | 例外処理 | Add exception handling to the script. |
エラー調査では、
SSH authentication failed、
connection timeout、
host key verification
などの英語をそのまま検索すると、
公式ドキュメントや技術情報を探しやすくなります。
理解度チェック
問題1.SSHによる情報取得を自動化する主な目的として 最も適切なものはどれですか。
- ネットワーク機器のIPアドレスをなくすため
- 複数機器の情報取得作業を効率化・標準化するため
- SSHをHTTPへ変換するため
- すべてのネットワーク障害を自動修復するため
解答を見る
複数機器へ同じ確認を行う処理を自動化することで、 作業時間や取得漏れを減らしやすくなります。
問題2.PythonからSSHを扱うライブラリとして、 この記事で使用したものはどれですか。
- NumPy
- Pandas
- Paramiko
- Matplotlib
解答を見る
問題3.ネットワーク機器で長いshowコマンドを取得するとき、 注意すべきCLI機能は何ですか。
解答を見る
出力途中で表示が停止すると、 自動取得で全結果を受け取れない可能性があります。
問題4.パスワードをPythonファイルへ直接記載することが 推奨されない理由を説明してください。
解答を見る
ソースコードの共有やGitへの登録などを通じて、 認証情報が漏えいする可能性があるためです。
問題5.50台を処理するとき、 1台へのSSH接続が失敗しても残り49台の処理を継続するために 必要な考え方は何ですか。
解答を見る
tryとexceptなどを利用し、
接続失敗を記録したうえで次の機器へ進みます。
実践演習:3台の機器から状態情報を収集する
次の要件を満たすPythonプログラムを考えてください。
構成
| 機器名 | 管理IPアドレス |
|---|---|
| RT01 | 192.168.10.1 |
| RT02 | 192.168.10.2 |
| SW01 | 192.168.10.11 |
取得する情報
show versionshow ip interface briefshow ip route
要件
- 3台へ順番にSSH接続する
- ページングを無効化する
- 3つのshowコマンドを実行する
- 結果を機器別に保存する
- 接続失敗時も次の機器へ進む
- パスワードをソースコードへ直接記載しない
1. 機器一覧を定義する
2. __________________
3. __________________
4. __________________
5. __________________
実装例を見る
import os
import time
from pathlib import Path
import paramiko
USERNAME = os.environ["SSH_USERNAME"]
PASSWORD = os.environ["SSH_PASSWORD"]
devices = [
{
"name": "RT01",
"host": "192.168.10.1"
},
{
"name": "RT02",
"host": "192.168.10.2"
},
{
"name": "SW01",
"host": "192.168.10.11"
}
]
commands = [
"show version",
"show ip interface brief",
"show ip route"
]
output_dir = Path("outputs")
output_dir.mkdir(exist_ok=True)
for device in devices:
client = None
try:
print(
f"Connecting to "
f"{device['name']} "
f"({device['host']})"
)
client = paramiko.SSHClient()
client.load_system_host_keys()
client.set_missing_host_key_policy(
paramiko.RejectPolicy()
)
client.connect(
hostname=device["host"],
username=USERNAME,
password=PASSWORD,
timeout=10,
look_for_keys=False,
allow_agent=False
)
channel = client.invoke_shell()
time.sleep(1)
if channel.recv_ready():
channel.recv(65535)
# Cisco IOS系の例
channel.send(
"terminal length 0\n"
)
time.sleep(1)
device_dir = (
output_dir /
device["name"]
)
device_dir.mkdir(
exist_ok=True
)
for command in commands:
print(
f" Execute: {command}"
)
channel.send(
command + "\n"
)
time.sleep(2)
output = ""
while channel.recv_ready():
output += (
channel
.recv(65535)
.decode(
"utf-8",
errors="ignore"
)
)
time.sleep(0.2)
safe_command = (
command
.replace(" ", "_")
.replace("/", "_")
)
filename = (
device_dir /
f"{safe_command}.txt"
)
filename.write_text(
output,
encoding="utf-8"
)
print(
f"{device['name']}: SUCCESS"
)
except (
paramiko.AuthenticationException
):
print(
f"{device['name']}: "
"AUTHENTICATION FAILED"
)
except paramiko.SSHException as e:
print(
f"{device['name']}: "
f"SSH ERROR: {e}"
)
except OSError as e:
print(
f"{device['name']}: "
f"CONNECTION ERROR: {e}"
)
finally:
if client is not None:
client.close()
このコードは学習用の基本例です。
実環境では、機器ごとのプロンプト判定、 コマンド完了判定、ページング処理、 認証方式、ホストキー管理、 ログ管理などを環境に合わせて設計してください。
発展課題
余裕があれば、次の機能も追加してみましょう。
- 実行日時をファイル名へ追加する
- 成功・失敗をCSVへ記録する
- 機器一覧をCSVから読み込む
- 取得コマンドを外部ファイルから読み込む
- 取得結果から「down」のインターフェースを抽出する
- 前日の取得結果との差分を確認する
自分の言葉で説明する課題
上司から次のように質問されました。
「SSHで情報取得を自動化すると、 手作業と比べて何が良くなるの?」
説明例を見る
SSHによる情報取得をPythonで自動化すると、 複数のネットワーク機器へ同じコマンドを自動実行できます。 そのため、定期確認の作業時間を短縮できるほか、 コマンドの実行漏れや取得方法のばらつきを減らせます。 また、取得結果をファイルへ保存すれば、 過去との比較や障害調査にも利用できます。
まとめ
- SSHとPythonを組み合わせると、 ネットワーク機器から情報を自動取得できる
- PythonからSSHを扱うライブラリとして Paramikoを利用できる
-
exec_command()では SSH経由でコマンドを実行して出力を取得できる -
対話型CLIを扱う場合は
invoke_shell()を利用できる - ネットワーク機器では ページングやプロンプトの扱いに注意する
- 機器一覧をループ処理すれば 複数機器へ同じ確認を実行できる
- 接続失敗や認証失敗を想定し、 例外処理とログを実装する
- パスワードをソースコードへ直接保存しない
- ホストキーを適切に検証し、 SSH接続先の信頼性を確認する
- 自動化は設定変更からではなく、 まず読み取り処理から始めると学習しやすい
ネットワーク自動化の第一歩は、 「人が繰り返している確認作業」を プログラムへ置き換えることです。
次の記事:Ansibleによる設定投入
今回は、 PythonからSSH接続してネットワーク機器の情報を取得しました。
SSHを直接プログラムから操作することで、 自動化の基本的な仕組みを理解できます。
一方、機器数や設定項目が増えると、 Pythonコードだけですべてを管理する方法は 複雑になりやすくなります。
次の記事では、 複数のネットワーク機器へ 同じ設定を効率的に適用する方法として、 Ansibleによる設定投入 を学びます。
参考ドキュメント
第6章では、 Python・SSH・Ansible・REST API・JSON・YAML・Git・ テレメトリーなどを使い、 ネットワーク運用を自動化・可視化する方法を学びます。

コメント