如何在Python中通过SSH代理使用ssh-agent进行并行SSH连接?
我有一个项目,需要经常通过ssh连接到很多服务器,执行一些命令。我原以为可以用Python脚本来实现这个需求,但我的要求似乎让所有可能的解决方案都不适用。我只能通过一个中间的堡垒服务器来访问这些服务器,而且只能使用通过ssh代理转发的ssh公钥。因此,我的要求是:
- 并行ssh,这样我就不用等上好几个小时才能在所有服务器上完成命令的执行。
- 支持ssh公钥,因为我不能使用密码认证。
- 支持ssh代理,因为我不能直接ssh连接到服务器,必须先通过一个ssh代理服务器。
- 支持ssh代理,因我需要将我的(预先加载的)ssh公钥通过代理服务器发送到目标服务器。
paramiko似乎能满足以上所有要求,除了第一个(并行ssh支持)。我找到一个叫做parallel-ssh的模块( https://github.com/pkittenis/parallel-ssh),它是paramiko的一个简单封装,但可惜的是,它似乎除了并行ssh和公钥认证之外,几乎不支持其他功能。
这是我现在的代码,它可以在一些不需要代理或ssh-agent的本地服务器上运行:
#!/usr/bin/python2.7
import sys
if 'threading' in sys.modules:
raise Exception('threading module loaded before patching!')
import gevent.monkey; gevent.monkey.patch_thread()
import paramiko
from pssh import ParallelSSHClient
paramiko.util.log_to_file("filename.log")
hosts = ['ocb100','netllama']
client_key = paramiko.DSSKey.from_private_key_file('/home/netllama/.ssh/id_dsa')
client = ParallelSSHClient(hosts, pkey=client_key)
cmds = client.exec_command('uptime')
1 个回答
0
你之前提到的parallel-ssh模块可以满足你的需求。特别是在代理和代理转发方面:
- 支持SSH代理 - 原生的代理和隧道支持,还有异步功能
- SSH代理转发 - 默认是开启的。在创建ParallelSSH对象时,设置
forward_ssh_agent=True
即可。
你使用ParallelSSH的示例:
from pssh import ParallelSSHClient
hosts = ['ocb100','netllama']
client = ParallelSSHClient(hosts, proxy_host='bastion')
output = client.run_command('uptime')
for host in output:
for line in output[host]['stdout']:
print(line)
执行上述代码的用户的SSH密钥会自动从正在运行的SSH代理中加载,你不需要指定pkey
参数。
如果你需要更改登录的用户,可以设置user
参数,比如ParallelSSHClient(hosts, user='netllama')
。
根据这个问题,SSH代理转发支持是在9月4日加入到ParallelSSH中的。
根据文档,ParallelSSH已经使用gevent来异步执行所有网络请求,它不像fabric那样使用线程或多进程。因此,你也不需要那些gevent的导入。
ParallelSSH的文档可以在这里找到。
编辑:已更新为最新的库API