直接调用命令时 SSH 停滞,但交互式运行时正常退出

2 投票
2 回答
3839 浏览
提问于 2025-04-10 23:51

我需要在远程机器上启动一个服务器,并获取这个服务器正在监听的端口号。当服务器启动时,它会在一个随机的端口上监听,并把端口号输出到错误信息中。

我想自动化这个过程,包括登录到远程机器、启动服务器进程以及获取端口号。我写了一个叫做"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"选项或者重定向标准输出。

2 个回答

0

如果你这样做会怎么样:

ssh <远程主机> '<你的命令> ;<你的正则表达式,使用awk或其他工具>'

举个例子:

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

这样做会连接到远程主机,执行你的程序,然后打印出所有用户为root的进程ID,或者任何描述中包含root的进程。

我用这种方法在远程机器上运行各种命令。需要注意的是,你想执行的命令要用单引号(')括起来,并且每个命令之间要用分号(;)分开。

3
s = p.stderr.readline()

我怀疑问题出在上面那行。当你通过ssh直接执行一个命令时,你并没有获得完整的终端环境(假设你在使用Linux),因此你无法读取错误信息。

而当你以交互方式登录时,输入、输出和错误输出都会为你设置好,所以你的脚本就能正常工作了。

撰写回答