在Python中实现守护进程
守护(Daemon)进程是linux中的一种重要的系统管理手段,一般名称都以d结尾,运行在系统的后台,完成一些监控或者服务的工作。在Python中也是可以实现这样的功能,不过现在好像也有外部库支持了,其实也不难。
实现原理
我们的任务就是需要将自己的python进程从shell中抽离出来,首先其父进程不能是shell否则会随着shell的结束而被清除,其次需要将自己的输入输出重定向一下。Linux中的setsid命令就可以让一个进程独立到后台运行,这里使用os模块的setsid函数达到同样的效果。
不过既然是守护进程还要能够结束才行,除了自己手动kill的方法,还可以使用pidfile这种方式,在生成的时候将自己的进程id写入一个pidfile中,这样如果再次运行就可以直接杀死之前的守护进程了。
代码示例
下面是我自己写的一个小例子
1 | #!/usr/bin/env python |
一个简单的时间戳写入程序,运行./timestampd start,可以启动守护进程,进程首先fork一份,然后父进程自己退出。子进程关闭自己的0,1,2标准输入输出流并将它们重新定向到/dev/null,同时设置umask为0,这样即使shell结束程序仍然在后台运行。可以用tail -f stamp-record.txt查看文件的增长( 这是tail的一个经典用法:) )
结束它的方法就是再次运行./timestampd end,根据之前记录的pidfile中的pid杀死守护进程即可。
疑惑
其实我还有一些不太明白的地方。
网上找到的很多教程都是需要fork两次,最后的孙子进程才能成为守护进程。对此,有博主给出的解释是如果fork一次出来的进程“访问终端文件时会失去控制权”,对于这一层由于我自己对linux的终端控制机制也不太了解,不能给出很合理的解释。
上面的代码是我看了supervisor(python写的进程监控工具)的源码之后把其中的守护进程部分抽取出来简化而成的,它的代码也就fork了一次就完成了任务,为什么网上那么多教程都是写着要fork两次呢,这两者之间有什么区别,还有待进一步研究…