在工作中会出现这样的场景:启动一个服务,需要让这个服务在后台运行,又不受其运行前的环境的影响(这些环境包括未关闭的文件描述符、控制终端、会话和进程组、工作目录以及文件创建掩码等)。
这时可以使用守护进程来控制程序的运行。
使程序后台运行的一般的做法有用 &
把这个服务放在后台运行,加上 nohup
,使得服务在终端关闭的情况下也不会停止。但这种做法在我实际使用中出现了意想不到的错误——我在使用 subprocess.Popen
来使用多进程过程中,在执行的语句里使用了 time.sleep()
进行睡眠,这时 nohup
控制的程序进程意外停止进程却未消失,而在不使用 nohup
将后台挂起的方法时,程序却能正常运行,没有停止。
于是考虑使用 python 编写守护进程来替代 nohup
方式。
daemon.py
1 | # !/usr/bin/env python |
run.py
1 | import sys, time |
路径拼接:
1 | >>> path1=os.path.abspath('.') |
daemon.py 的使用
- 启动:
python daemon.py start
- 停止:
python daemon.py stop
- 重启:
python daemon.py restart
logs 目录
watch_stdout.log
:日志文件watch_process.pid
:进程号文件,daemon.py
程序根据这个文件是否存在来判断服务有没有在运行。- 当使用
python daemon.py start
启动服务时,daemon.py 会新建一个 watch_process.pid 文件 - 当使用
python daemon.py stop
停止服务时,daemon.py 会删除 watch_process.pid 文件
- 当使用
强杀进程:如果 python 服务进程存在,但 watch_pid 文件不存在,那么使用 python daemon.py stop
将无法停止 python 服务,这时可以查出 python 服务进程的进程组 id ,然后使用 kill -9 -id 来将一组进程停止。
查看进程关系:
1 | $ ps j -A | grep python |
如上的进程组,可以用 kill -9 -10566
将一组进程杀死。
进程树:
1 | cat ./logs/watch_process.pid |
1 | cat ./logs/watch_process.pid |
参考链接
具体的原理可以参考: