在多跳SSH连接上重新建立交互式Shell

时间:2019-02-08 04:57:28

标签: paramiko openssh ssh-tunnel

我有一个用例,其中我需要通过主机“ B”和“ C”将主机“ A” ssh转换为主机“ D”(我希望能够将解决方案应用于尽可能多的中间主机)可能):

  

A ==> B ==> C ==> D

建立与D的连接后,我想运行命令列表[“ comm1”,“ comm2”,“ comm3”],并以[“ output1”,“ output2”,“ output3”接收响应“]在主机A上。 我想出的唯一策略是,一旦到达主机D:

  1. 执行连接。invoke_shell()
  2. 发送comm1,轮询通道以进行输出,收集响应并将其插入空白列表中
  3. 关闭由connection.invoke_shell()创建的通道
  4. 建立一个新的交互式shell频道
  5. 对comm2和comm3重复步骤1至5

当我进行开发时,意识到重新建立交互式外壳程序通道会导致EOFError。我很想在步骤3中关闭通道会终止从主机A到主机D的整个SSH会话。

但是,必须关闭通道并为每个命令启动一个新的交互式外壳,否则,您将作为一个大文本块读取通道的完整输出(包含所有3个命令的输出) ,然后您必须使用屏幕抓取来处理,这并不理想。 上面的算法可行吗?如果是,如何使用paramiko来实现它,为什么我会收到EOFError异常?

我也尝试使用Fabric实现此目的。它适用于某些设备,但不适用于cisco设备。原因是Fabric还使用了paramiko的ssh远程命令执行功能,某些Cisco设备也不支持该功能(请查看client.exec_command)。因此,交互式会话是唯一的方法。

1 个答案:

答案 0 :(得分:0)

为简单起见,请考虑无跳情况:

$ ssh -i key user@host 'echo command; echo control'
command
control
$ ssh -i key user@host 'echo command; echo control' >/dev/null
$ ssh -i key user@host 'echo command; echo 1>&2 control' >/dev/null
control

换句话说,我们有两个输出通道...