我有一个看起来像这样的JSON对象:
{UID_1:{
jumpboxes:[jump_ip1, jump_ip2,...],
hosts: [host_ip1, host_ip2,...],
...},
UID_2:{...
对跳转框的身份验证是通过kerberos(无密码)进行的,对主机的身份验证是通过密码进行的,并且仅通过跳转主机才能看到主机。我不知道哪些IP可以正常工作,哪些IP阻塞或无响应等。因此,我需要找到第一个允许我打开SSH会话的路径。
我所能做的就是用以下方法检查跳转主机的退出代码:
jumpip = ''
for i in json[uid][jumpboxes]:
if os.system('ssh {}@{}'.format(username,i))>0:
continue
else:
jumpip = i
break
这使我的第一个可正常工作的Jumpbox ip没有问题,但是,拥有用于与第二个主机建立ssh连接的密码并不容易检查其退出代码。
有多种打开隧道的方法-使用os.system()以及将sshpass与会话代理一起使用(类似:
if os.system('sshpass -p {} ssh -o ProxyCommand="ssh {}@{} nc {} 22" {}@{} -t {}'.format(password, user, jumpip, hosts[j], user, hosts[j], remote_cmd))>0:....
(在上下文中,我们假设sshpass命令看起来像这样:sshpass -p Password123! -o ProxyCommand="ssh user@jumpbox nc hostip 22" user@hostip -t ll
或在子外壳中使用os.system('ssh user@jumpbox -t ping {} -c 5'.format(hosts[j]))
之类的品脱,尽管ping会返回退出代码,但ICMP回显答复并不意味着我能够打开隧道(例如,守护程序可能被卡住或崩溃了,等等),或者我可以执行try-except-else块,尝试向ssh打开ssh会话。远程主机通过带有pexpect或subrpocess.popen并通过stdio传递管道的Jumpbox进行操作,因此允许我推送密码,如果那不能引发自定义异常,但是我不知道如何从ssh客户端获取退出代码,所以我可以检查状态...
对于我来说,这两个都不足够强大,因此我宁愿正确地遍历IP,对此我也乐意为您提供建议。
有点背景-隧道将用于启动nohup-ed命令,然后将其关闭。该脚本使用多重处理和池来遍历所有这些,因此我将启动它们,然后进行循环以检查其状态并检索在主机上执行的远程脚本的结果。我知道os.system已过时,我应该使用子进程,但这对于用例而言不是必需的,因此我并不在乎。我正在寻找一种聪明的方法来迭代可能的路径,这将给定一个长度为n
的跳转框列表和一个长度为m
且超时时间为x
秒的主机列表最多n*m*x
秒来找出并缩短时间。
一旦我找到了打开隧道所需的正确IP,我还将使用pexpect(本身使用paramiko)与远程主机进行交互。
谢谢!
答案 0 :(得分:0)
Paramiko的exit_status_ready函数将告诉您退出状态。
如果远程进程已退出并返回退出,则返回true 状态。如果您不想,可以使用它来轮询进程状态 阻止recv_exit_status。请注意,服务器可能不会返回 在某些情况下(例如服务器故障)退出状态。
在查看pexpect的源代码时,我看不到它在哪里使用了Paramiko,因此您可能需要用Paramiko代码替换所有的pexpect代码。 Paramiko为您提供了建立SSH连接的所有低级方面的很多控制权,因此您可能需要一点点粗略的了解,但确实可以为您控制整个过程。
答案 1 :(得分:0)
我知道了-如果出现提示,pexpect提供了退出代码,即我做了类似的事情
try-catch
感谢所有输入。