远程启动 Python 程序并在后台运行

3

我需要使用fabfile从远程盒子上启动一些程序并获取结果,但由于程序需要很长时间才能完成,所以我希望它在后台运行,这样我就不必等待。 因此,我尝试使用os.fork()来使其工作。 问题是,当我ssh到远程盒子上并在那里使用os.fork()运行程序时,程序可以正常在后台工作,但是当我尝试使用fabfile的run和sudo远程启动程序时,os.fork()无法工作,程序会默默地死掉。 所以我切换到Python-daemon来将程序变成守护进程。 长时间以来,它完美地工作。 但现在当我开始让我的程序读取一些Python shelve字典时,python-daemon就不能再工作了。 看起来如果您使用python-daemon,则shelve字典无法正确加载,我不知道为什么。 除了os.fork()和Python-daemon之外,有没有其他解决我的问题的方法?


定时任务?看起来是这样的。 - Jakob Bowyer
登录SSH时,使用shell的nohup命令将其在后台启动,如何? - Sven Marnach
2个回答

4
如果我理解你的问题正确,我认为你把它搞得太复杂了。 os.fork() 是用于多进程,而不是在后台运行程序。
假设出于讨论的目的,您想运行program.sh并收集其发送到标准输出的内容。 使用fabric,可以在本地创建以下文件:
fabfile.py:
from fabric.api import run
def runmyprogram():
    run('./program.sh > output 2> /dev/null < /dev/null &')

接下来,在本地运行:

fab -H remotebox runmyprogram

该程序将在远程执行,但Fabric不会等待其完成。您需要稍后收集输出文件,可能使用scp。"&"使其在远程机器上在后台运行,而必须使用输出重定向避免出现挂起的fabric会话
如果您不需要使用Fabric,有更简单的方法来完成此操作。您可以分别进行ssh并运行。
nohup ./program.sh > output &

如果您需要定期执行此操作,那么可以使用cron job来定时运行并在需要时收集输出结果,这可能是更好的选择。

如果您不想后期获取输出文件,则可以使用:

fabfile.py:

稍后再回来检查输出结果。

from fabric.api import run
def runmyprogram():
    run('./program.sh')

然后,在您的本地机器上执行以下操作:

fab -H remotebox runmyprogram > output &

这些任务将在远程运行,并将所有输出放回本地输出文件中。它在本地机器的后台运行,因此您可以做其他事情。但是,如果本地和远程机器之间的连接可能会中断,最好使用第一种方法,以便输出始终安全存储在远程机器上。


嗨,Chris。我认为当程序仍在远程盒子中运行时,如果杀死fab,则程序将立即停止运行。您会采取什么特殊措施来避免这种情况发生?只需在fab命令的末尾添加“&”吗?非常感谢您的帮助! - Sheng
盛,远程程序将继续运行,即使fab在本地被杀死(至少在我的测试中是这样的;我找不到任何文档来确认这一点)。尽管如此,我已经更新了我的答案,以提供更好的方法,如果您宁愿在远程后台启动作业并让fabric立即在本地完成。 - Chris P
Chris,现在我又可以让Python守护程序正常工作了,所以我会继续使用旧方法。但是如果你的解决方案适用于我的问题,那么它可能是一种优雅的解决方案,我明天午休时会试一下。非常感谢你的更新! - Sheng

2
对于未来看到这篇文章的人。Python-daemon仍然可以工作。只需确保在同一个进程中加载shelve字典。因此,以前shelve字典是在父进程中加载的,当python-daemon生成子进程时,字典处理程序不会正确传递。当我们修复这个问题后,一切都正常工作了。
感谢那些在这个线程上提出有价值评论的人!

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接