いきなりサンプルです。
import paramiko
def nested_ssh(address1, account1, address2, account2, commands, pre_command=None):
"""
多段SSHを実行する関数
:param address1: 最初のホストのアドレス
:param account1: 最初のホストのアカウント情報 (username, password)
:param address2: 2番目のホストのアドレス
:param account2: 2番目のホストのアカウント情報 (username, password)
:param commands: 実行するコマンドとその期待される出力のリスト
[{"command": "cmd1", "expected": "exp1"}, ...]
:param pre_command: コマンド実行前に実行するコマンド(オプション)
:return: コマンドの実行結果と期待値との比較結果のリスト
"""
# 最初のホストに接続
ssh1 = paramiko.SSHClient()
ssh1.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh1.connect(address1, username=account1[0], password=account1[1])
# 2番目のホストへのチャンネルを開く
transport = ssh1.get_transport()
dest_addr = (address2, 22)
local_addr = ('127.0.0.1', 1234)
channel = transport.open_channel("direct-tcpip", dest_addr, local_addr)
# 2番目のホストに接続
ssh2 = paramiko.SSHClient()
ssh2.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh2.connect(address2, username=account2[0], password=account2[1], sock=channel)
# pre_commandがある場合は実行
if pre_command:
stdin, stdout, stderr = ssh2.exec_command(pre_command)
stdout.channel.recv_exit_status() # コマンドの完了を待つ
results = []
# コマンドを順次実行し、結果を確認
for cmd in commands:
stdin, stdout, stderr = ssh2.exec_command(cmd["command"])
output = stdout.read().decode().strip()
expected = cmd["expected"].strip()
match = output == expected
results.append({
"command": cmd["command"],
"output": output,
"expected": expected,
"match": match
})
# 接続を閉じる
ssh2.close()
ssh1.close()
return results
# 使用例
address1 = 'host1'
account1 = ('user1', 'pass1')
address2 = 'host2'
account2 = ('user2', 'pass2')
commands = [
{"command": "pwd", "expected": "/home/user2"},
{"command": "ls", "expected": "file1\nfile2\nfile3"},
{"command": "echo 'Hello'", "expected": "Hello"}
]
pre_command = 'cd /some/directory'
results = nested_ssh(address1, account1, address2, account2, commands, pre_command)
for result in results:
print(f"Command: {result['command']}")
print(f"Output: {result['output']}")
print(f"Expected: {result['expected']}")
print(f"Match: {result['match']}")
print("---")