【问题标题】:Create and maintain several ssh sessions in Python在 Python 中创建和维护多个 ssh 会话
【发布时间】:2012-03-08 12:10:53
【问题描述】:

一旦我的程序启动,它会打开任意数量的 ssh 会话(用户定义)并无限期地在服务器上运行特定命令(当真正循环时)或直到用户退出。出于效率原因,我只想创建每个会话一次,然后能够运行命令直到用户退出。

如何在 python 中做到这一点?我在另一篇文章中遇到了一个很酷的方法,它使用subprocess 运行命令并捕获其 STDOUT。如何先启动会话,然后运行循环命令?

任何指向 Python 中类似进程的东西的链接也将不胜感激。这是我的第一个 python 应用程序。

【问题讨论】:

  • 我想这已经做过了,我不记得名字了,但它是一个开源项目(python也是),它可以让你同时通过SSH管理多台远程机器。
  • 听起来很酷。我的应用程序确实会从中受益(尽管自己编写代码将是一个很好的学习过程),尽管它需要一些额外的功能。

标签: python ssh subprocess


【解决方案1】:

选项 1: 您可以通过使用 PIPE 重定向输入来重新使用 ssh 进程。

这是一个基本的例子:

[(Z) </tmp> ]% touch input_file
[(Z) </tmp> ]% tailf input_file | ssh <remote_host>

现在尝试在文件中写入一些内容

[(Z) </tmp> ]% echo "date" >> /tmp/input_file

这是一种在 Python 中使用 subprocess 模块来使用它的方法。

import subprocess
SSH_CMD = "cat -| /usr/bin/ssh -o PasswordAuthentication=no -T -x %s "
HOSTNAME = "127.0.0.1"
s = subprocess.Popen(SSH_CMD%HOSTNAME , shell=True, close_fds=True, 
stdin=subprocess.PIPE, stderr=subprocess.PIPE, stdout=subprocess.PIPE)

这会启动一个可以重复使用的子进程。请注意,close_fds=True 是必需的,因为存在已知错误 (http://bugs.python.org/issue2320)。

>>> REMOTE_CMD = "date"
>>> s.stdin.write( REMOTE_CMD +
... "\necho 'remote command completed with exit code = '$?\n")
>>> s.stdout.readline()
'Thu Feb 16 20:01:36 PST 2012\n'
>>> s.stdout.readline()
'remote command completed with exit code = 0\n'

echo 'remote command completed with exit code = '$?\n 行用于知道远程命令已完成并且已完成写入 s.stdout。这对于了解远程命令的退出代码也很有用。

使用相同的子进程执行另一个远程命令:

>>> REMOTE_CMD = "uptime"
>>> s.stdin.write( REMOTE_CMD +
... "\necho 'remote command completed with exit code = '$?\n")
>>> s.stdout.readline()
' 20:02:17 up 28 days,  9:15, 48 users,  load average: 0.01, 0.02, 0.05\n'
>>> s.stdout.readline()
'remote command completed with exit code = 0\n'

回到你的问题,一旦你创建了一个 ssh 子进程,你就可以继续发送远程命令。用户退出后,您可以终止子进程。

>>> s.kill()

选项 2:我从来没有使用过这个,但是 ssh 有一个 ControlMaster 选项可以重新使用 ssh。检查 ssh_config(5) 的手册页

【讨论】:

  • 我将对此进行调查作为解决方案,看起来很漂亮。感谢您的帮助,我会让您知道结果如何。
  • 嗨,使用您的解决方案,如果我将 ls 作为远程命令,我将不知道管道会有多长时间的数据。我希望在某个时候停下来,然后发送下一个命令..
  • 是的,没错。要知道何时停止执行 readline(),您必须将每个输出行与“remote command completed with exit code = XX”进行比较(注意在我的原始代码 sn-p 中 REMOTE_CMD 之后添加的 echo 命令)。它也有助于我了解 REMOTE_CMD 的 exit_code。但我同意,这有其缺点。
【解决方案2】:

尝试使用 pexpect 模块。它允许打开和维护 ssh 会话,您可以重复使用这些会话来发送多个命令。您可以发送任何命令并期待特定的输出,您可以根据这些输出执行其他逻辑操作。

【讨论】:

    【解决方案3】:

    尝试将其与多线程混合使用?

    【讨论】:

      【解决方案4】:

      暂时忽略 Python,你可以通过添加这个来复用 ssh 会话

      ControlMaster auto
      ControlPath /tmp/ssh_mux_%h_%p_%r
      ControlPersist 1h
      

      到您的~/.ssh/config 文件。连接到机器一次后,与这台机器的 ssh 会话将保持打开状态,随后的命令将在这台机器上几乎立即执行。然后,您可以使用 Python 子进程调用 ssh 并根据需要在该机器上执行命令,会话将被重用,而无需执行任何特殊操作。

      如果您不想让会话多路复用默认行为(或者您正在为可能没有它的其他用户进行部署,那么您也可以使用指向备用配置文件的 -F 标志调用 ssh作为他们的默认值)。

      【讨论】:

      • 这听起来很有希望。我会到处搜索 ssh 缓存,如果这就是我想要的路线,我会告诉你。谢谢
      • 如果没有记错的话,你在谷歌上搜索“多路复用”会更幸运。还有一些caveats 也值得了解。
      • 所以这看起来确实很酷,但是当通过套接字发送大量数据时它似乎失败了。看到运行的命令是用户指定的,我不能确定它不会失败。我想我会找到另一种方法来做到这一点。不过感谢这个很棒的花絮。
      猜你喜欢
      • 2019-08-16
      • 2023-03-14
      • 2019-05-11
      • 1970-01-01
      • 2011-11-08
      • 2013-11-18
      • 1970-01-01
      • 2011-03-03
      • 2013-09-11
      相关资源
      最近更新 更多