使用python-rq在远程服务器上执行长任务
我写了一段代码,执行起来非常耗时(需要2到3天),我想把它放到服务器上去执行。这个代码里有很多类和函数相互作用,但最后所有的执行都是通过一个叫做test2的函数来完成的。我发现对我来说,使用任务队列可能是个解决方案,而且我并不需要同时执行多个任务,所以我觉得RQ可能适合我。
#action_test.py
import action2
def test1():
fl = action2.FollowersList()
mech = action2.Mechanics()
manager = action2.Manager()
manager.launch(mech,fl)
for i in range(0,10):
manager.iterate(mech,fl)
def test2():
messageList = []
fl = action2.FollowersList()
mech = action2.Mechanics()
manager = action2.Manager()
manager.launch(mech,fl)
for i in range(0,2000):
message = manager.iterate(mech,fl)
messageList.append(message)
return messageList
我在远程服务器上设置了Redis,并以守护进程模式运行。然后我写了一个简单的模块,主要是把我的test2函数放进队列里。
#app.py
from rq import Connection, Queue
from redis import Redis
from action_test import test2
def main():
# Tell RQ what Redis connection to use
redis_conn = Redis()
q = Queue(connection=redis_conn) # no args implies the default queue
# Delay calculation of the multiplication
job = q.enqueue(test2, timeout = 259200)
print job.result # => None
if __name__ == '__main__':
main()
接着我遇到了一个问题:在python-rq的文档网页上(http://python-rq.org/docs/workers/),说启动一个工作者的方法是从命令行执行
$ rqworker
但是这个工作者并不是以守护进程的方式启动的,因此当我通过ssh连接到这个远程服务器时,如果我的ssh连接断开了,工作者也会停止,这样的情况我并不想要。要在我的代码执行的2到3天里保持ssh连接是很不方便的,这样就违背了我使用python-rq的初衷。有没有什么办法可以解决这个问题?也许python-rq的工作者应该不是从命令行启动,而是以守护进程的方式启动?
3 个回答
你可以使用supervisord这个工具。它可以帮助你设置一个后台进程,用来运行任务。而且它的配置也非常简单。
根据我的理解,你根本不需要用到 python-rq
。消息队列通常是用来在分布式系统中进行通信的,这对那些只想在远程服务器上运行长时间脚本的人来说,实在是太复杂了。你可以直接运行你的脚本,而不需要 rqworker
。只需在你的 action_test.py
脚本中添加 if __name__=='__main__': test2()
,然后就可以从命令行运行这个脚本了:
python test_action.py
正如你所提到的,当你关闭 SSH 会话时,你的脚本也会被终止。这是因为 Unix/Linux 有一种叫做“信号”的机制:系统会向你的任务发送一个“挂起”信号,也就是 SIGHUP
。马丁提到过 nohup
,这也是一个可行的解决方案(比如 nohup python test_action.py
),但对于一个只想运行长脚本的初学者来说,这有点复杂。
对你来说,更简单的解决办法是使用 screen
。Screen 可以创建一个虚拟终端,让你可以从一个 shell 中断开连接,然后再重新连接。如果你已经安装了 screen,只需运行 screen
,它就会为你创建一个新的虚拟终端。接下来,像往常一样运行你的程序: python test_action.py
。一旦程序启动,按 Ctrl+A 然后按 D 来断开连接。现在你可以断开 SSH 会话,但这个任务会在虚拟终端中继续运行,就好像什么都没发生一样。稍后你可以重新 SSH 到服务器,然后输入 screen -r
来恢复使用那个终端。
更多信息请查看这里: https://unix.stackexchange.com/questions/24658/nohup-vs-screen