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

时间:2008-08-28 21:48:09

标签: python ssh

我需要在远程计算机上启动服务器并检索服务器进程正在访问的端口号。调用时,服务器将侦听随机端口并在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”标志或重定向标准输出。

3 个答案:

答案 0 :(得分:3)

s = p.stderr.readline()

我怀疑是上面这行。当您通过ssh直接调用命令时,您没有得到完整的pty(假设是Linux),因此没有stderr可以读取。

当您以交互方式登录时,会为您设置stdin,stdout和stderr,因此您的脚本可以正常工作。

答案 1 :(得分:0)

如果您执行以下操作会怎样:

ssh <remote host> '<your command> ;<your regexp using awk or something>'

例如

ssh <remote host> '<your program>; ps aux | awk \'/root/ {print $2}\''

这将连接,执行并打印任何用户root或其描述中具有root的任何进程的每个PSID。

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

答案 2 :(得分:0)

@Ben Collins

我认为你对斯特德尔是一个问题是正确的。我很确定它在readline()调用时阻塞了。

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

@Misha M

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