2011-09-27 123 views
3

我有一堆脚本用于跨多个服务器启动类似的进程。我想将它们压缩成一个叫做'START'的Python脚本,但是当它通过ssh运行时会发生一些奇怪的事情。调用通过ssh创建子进程的Python脚本挂起

$ ./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 

回答

0

不要使用shlex与子一起叫。 It doesn't do what you expect。相反,给子命令的Python列表,像

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

如何从ssh启动脚本与直接调用脚本受此影响?该脚本直接调用时工作正常。 – dmcauslan

0

当你这样做:

ssh some_host remote_command remote_cmd_param 

则是正常的remote_command完成之前SSH不会返回控制。如果你想,否则你需要将它发送到背景在最后添加&

ssh将remote_command的stdout重定向到其(本地)stdout。如果你没有看到任何输出,这可能是因为remote_command没有设置任何标准输出,而是尝试将它发送到控制台。这就是为什么你不能这样做:

ssh remote_host mC# or any other command using terminal 
+0

START脚本确实输出一些调试信息,该信息使用打印输出到STDOUT。当我直接调用脚本时,程序将显示此信息并退出。当我通过ssh调用脚本时,只会在子进程终止时打印信息。子进程本身将其他数据记录到它自己的stdout(在Popen调用中显式设置)。 – dmcauslan

0

你应该把这个在START_APP_A

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

然后它会工作,并从APP_A输出都将进入一个日志文件,则您可以在检查需要。

请注意,如果您需要在APP_A运行时检查此输出,则需要更改APP_A,以便在打印后刷新标准输出或将标准输出更改为无缓冲。

+0

不是“stdout = open(file_out,'a +'),stderr = subprocess.STDOUT”是否已经重定向IO? – dmcauslan

+0

也许它确实,也许它没有。当你用shell脚本包装它的时候,它可以工作,为什么不使用shell。另外,我不清楚哪些位在本地运行,哪些位在远程运行。你错过的一件事是stdin,它可能或可能不重要。在任何情况下,这一行shell脚本将与任何语言的任何应用程序一起工作,以在您使用ssh连接到的远程服务器上运行它。阅读nohup的手册页以了解更多信息。 –