通过ssh调用创建子进程的Python脚本挂起

4 投票
3 回答
1786 浏览
提问于 2025-04-17 03:12

我有一堆脚本,用来在多个服务器上启动类似的进程。我想把它们合并成一个叫做'启动'的Python脚本,但在通过ssh运行时出现了一些奇怪的问题。

$ ./START APP_A 这个命令按预期工作:APP_A被启动并开始运行。控制权会立即返回到控制台(在APP_A还没结束之前)。

$ ssh localhost /path_to/START APP_A 这个命令有点问题:APP_A被启动并开始运行,但ssh在APP_A结束之前不会把任何输出打印到屏幕上,也不会把控制权返回到控制台。

我猜这可能是信号或文件句柄的问题,但我不知道怎么解决。这里是看起来引起问题的Popen调用:

sub = subprocess.Popen(shlex.split(cmd), stdout=open(file_out, 'a+'), stderr=subprocess.STDOUT, close_fds=True)
print 'New PID:', sub.pid

我在RHEL上使用的是Python 2.4.3。

编辑:把Python脚本包裹起来似乎能解决这个问题:

DIR="$( cd "$( dirname "$0" )" && pwd )"
pushd $DIR >> /dev/null
./START $1 &
popd >> /dev/null

3 个回答

0

你应该把这个放在 START_APP_A 里。

nohup /path/to/APP_A >/path/to/log 2>&1 </dev/null &

这样就能正常工作了,APP_A 的所有输出都会记录到一个日志文件里,等你需要的时候可以查看。

需要注意的是,如果你想在 APP_A 运行的时候查看这些输出,你就得修改 APP_A,让它在打印后立即刷新输出,或者把输出设置为不缓存。

0

当你执行以下命令时:

ssh some_host remote_command remote_cmd_param

那么在远程命令执行完成之前,ssh 不会返回控制权,这是正常的。如果你想要让它在后台运行,可以在命令末尾加上 &

ssh 会把远程命令的输出(stdout)重定向到你本地的输出。如果你没有看到任何输出,可能是因为远程命令没有将任何内容发送到标准输出,而是尝试将其发送到控制台。例如,这就是为什么你不能这样做:

ssh remote_host mc # or any other command using terminal
0

不要用shlex来和subprocess一起使用。它的效果可能和你想的不一样。相反,应该给subprocess传一个Python列表,里面放着你要执行的命令,比如:

subprocess.Popen(['/some/program', 'arg1', 'arg2', 'arg3'])

撰写回答