supervise启动lighttpd或其他daemon进程问题(linux shell)
[| 2011/10/09 23:27]
今天有同事问到为什么supervise启动lighttpd的时候,lighttpd的pid文件是空的。我试了下,发现果然如此。
首先猜想是不是supervise动了手脚导致程序getpid得到空值,写了个printf getpid的小例子跑了下发现正常。
后来尝试用supervise启动lighttpd,发现supervise每隔1s就尝试启动lighttpd,即使lighttpd已经正常运行了。用刚才的小例子时不会重复尝试,只有被保护程序挂掉后才尝试重启。
后来突然想到lighttpd的两次fork。由于lighttpd进程是以daemon进程形式运行的,在启动过程中有两次fork子进程,然后父进程退出的操作。
supervise中,启动被监控程序的流程是supervise先fork一个自己,子进程调用execvp来启动被监控程序。父进程记录fork时获得的进程号,监控起来。显然,lighttpd第一次fork后,子进程就已经退出了,故supervise以为被监控进程挂了,于是尝试再次启动lighttpd。由于端口被占用的缘故,lighttpd未能启动,由于lighttpd的启动会清空pid文件,而启动失败又没有往里面写入有效进程号,所以pid文件就是空的了。
不使用supervise,通过普通方式两次启动lighttpd,第二次报端口被占用,此时pid文件为空,验证了以上的推论。
首先猜想是不是supervise动了手脚导致程序getpid得到空值,写了个printf getpid的小例子跑了下发现正常。
后来尝试用supervise启动lighttpd,发现supervise每隔1s就尝试启动lighttpd,即使lighttpd已经正常运行了。用刚才的小例子时不会重复尝试,只有被保护程序挂掉后才尝试重启。
后来突然想到lighttpd的两次fork。由于lighttpd进程是以daemon进程形式运行的,在启动过程中有两次fork子进程,然后父进程退出的操作。
supervise中,启动被监控程序的流程是supervise先fork一个自己,子进程调用execvp来启动被监控程序。父进程记录fork时获得的进程号,监控起来。显然,lighttpd第一次fork后,子进程就已经退出了,故supervise以为被监控进程挂了,于是尝试再次启动lighttpd。由于端口被占用的缘故,lighttpd未能启动,由于lighttpd的启动会清空pid文件,而启动失败又没有往里面写入有效进程号,所以pid文件就是空的了。
不使用supervise,通过普通方式两次启动lighttpd,第二次报端口被占用,此时pid文件为空,验证了以上的推论。