ssh在直接调用命令时挂起,但在交互式运行时干净退出

时间:2020-03-05 18:44:42  来源:igfitidea点击:

我需要在远程计算机上启动服务器,并获取服务器进程进行lsitening的端口号。调用时,服务器将在随机端口上侦听并在stderr上输出端口号。

我想自动化登录到远程计算机,启动该过程以及检索端口号的过程。我编写了一个名为"invokejob.py"的Python脚本,该脚本驻留在远程计算机上,充当调用该作业然后返回端口号的包装器,如下所示:

import re, subprocess
executable = ... # Name of executable
regex = ... # Regex to extract the port number from the output
p = subprocess.Popen(executable,
    bufsize=1, # line buffered
    stderr=subprocess.PIPE
    )
s = p.stderr.readline()
port = re.match(regex).groups()[0]
print port

如果我以交互方式登录,则此脚本有效:

$ ssh remotehost.example.com
Last login: Thu Aug 28 17:31:18 2008 from localhost
$ ./invokejob.py
63409
$ exit
logout
Connection to remotehost.example.com closed.

(注意:成功注销,它没有挂起)。

但是,如果我尝试从命令行调用它,它将挂起:

$ ssh remotehost.example.com invokejob.py

有谁知道为什么它挂在第二种情况下,我该怎么做才能避免这种情况?

请注意,我需要检索程序的输出,因此我不能只使用ssh" -f"标志或者重定向标准输出。

解决方案

回答

s = p.stderr.readline()

我怀疑这是上面的线。当我们直接通过ssh调用命令时,我们不会获得完整的权限(假设使用Linux),因此就没有可读取的stderr了。

交互式登录时,将为我们设置stdin,stdout和stderr,因此脚本可以工作。

回答

如果我们执行以下操作怎么办:

ssh <远程主机>'<命令>; <我们使用awk或者其他东西的正则表达式>'`

例如

ssh &lt;远程主机>'&lt;程序>; ps aux | awk \'/ root / {print $ 2} \''

这将连接到,执行,然后打印任何用户root或者描述中带有root的任何进程的每个PSID。

我已使用此方法在远程计算机上运行各种命令。问题是用单引号(')将要执行的命令包装起来,并用分号(;)分隔每个命令。

回答

@本·柯林斯

我认为我们将stderr视为问题是正确的。我很确定它阻塞了readline()调用。

最后,我放弃了,并决定使用pexpect中的pxssh模块来自动执行与ssh会话的交互。

@Misha M

不幸的是,分号把戏在这里不起作用:它阻止了我程序的执行。