如何在Linux上管理基于Python的守护进程?

5 投票
6 回答
3259 浏览
提问于 2025-04-15 23:24

我有一个用Python写的程序,想把它当成一个后台服务来运行。目前我用的办法有点笨,就是先用screen-d -m name来启动它,然后用pkill -9 -f name来结束它。

最终我会把这个程序迁移到我们这里更好的系统上(所以我不打算修改这个程序),但在这段时间里,我想找个更干净的方法来处理这个问题。

我现在的想法是通过一个inti.d脚本把它作为后台任务启动,但我该怎么写代码来结束它呢?

6 个回答

3

如果你想用Python代码来实现这个功能,这里有一个很常见的C语言方法被移植到了Python上,我自己也在用。这个方法运行得非常顺利,而且你还可以选择输出到文件。

import os
import signal
def daemonize(workingdir='.', umask=0,outfile='/dev/null'):
#Put in background
pid = os.fork()
if pid == 0:
    #First child
    os.setsid()
    pid = os.fork() #fork again
    if pid == 0:
        os.chdir(workingdir)
        os.umask(umask)
    else:
        os._exit(0)
else:
    os._exit(0)

#Close all open resources
try:
    os.close(0)
    os.close(1)
    os.close(2)
except:
    raise Exception("Unable to close standard output. Try running with 'nodaemon'")
    os._exit(1)

#Redirect output
os.open(outfile, os.O_RDWR | os.O_CREAT)
os.dup2(0,1)
os.dup2(0,2)

接下来,你可以使用信号来捕捉程序收到的终止信号,然后优雅地退出。下面是来自Python文档的例子。

import signal, os

def handler(signum, frame):
    print 'Signal handler called with signal', signum
    raise IOError("Couldn't open device!")

# Set the signal handler and a 5-second alarm
signal.signal(signal.SIGALRM, handler)
signal.alarm(5)

# This open() may hang indefinitely
fd = os.open('/dev/ttyS0', os.O_RDWR)

signal.alarm(0)          # Disable the alarm
6

在Linux系统中,有一个叫做 start-stop-daemon 的工具,它是init.d工具的一部分。

这个工具非常灵活,可以用不同的方法来获取你服务器的进程ID(pid)。

另外,还有一个文件叫做 /etc/init.d/skeleton,可以用作你自己init.d脚本的基础。

如果你的目标平台是基于Debian的,创建一个Debian包来部署它是个不错的主意,因为这样可以帮助你的守护进程更好地融入系统的其他部分。而且这并不太复杂(如果你之前做过十次的话;-)

撰写回答