什么是守護(hù)進(jìn)程
守護(hù)進(jìn)程(daemon)是一種特殊的進(jìn)程,它的生命周期很長,它在后臺運(yùn)行并且沒有控制終端(這樣可以保證守護(hù)進(jìn)程不會(huì)接收到各種來自終端的信號)。比如:crontab、sshd、nginx等,都會(huì)使用守護(hù)進(jìn)程的形式運(yùn)行,確保可以一直正常的提供服務(wù)。
如何實(shí)現(xiàn)守護(hù)進(jìn)程
- fork子進(jìn)程,父進(jìn)程退出(當(dāng)前子進(jìn)程會(huì)成為init進(jìn)程的子進(jìn)程)
- 子進(jìn)程調(diào)用setsid(),開啟一個(gè)新會(huì)話,成為新的會(huì)話組長,并且釋放于終端的關(guān)聯(lián)關(guān)系
- 再次fork子進(jìn)程,父進(jìn)程退出(可以防止會(huì)話組長重新申請打開終端)
- 關(guān)閉打開的文件描述符
- 改變當(dāng)前工作目錄chdir
- 清除進(jìn)程的umask
PHP實(shí)現(xiàn)
/** * daemon(守護(hù)進(jìn)程) PHP實(shí)現(xiàn) * @author zhjx922 */$pid = pcntl_fork();if ($pid == -1) { die(‘創(chuàng)建子進(jìn)程失敗’);} else if ($pid) { //第一次退出父進(jìn)程 exit(0);}//setsidposix_setsid();echo “成功輸出,脫離終端” . PHP_EOL;sleep(5);$pid = pcntl_fork();if ($pid == -1) { die(‘創(chuàng)建子進(jìn)程失敗’);} else if ($pid) { //第二次退出父進(jìn)程(之前fork出來的子進(jìn)程) exit(0);}echo “依然可以輸出” . PHP_EOL;sleep(5);//關(guān)閉各種描述符@fclose(STDOUT);@fclose(STDERR);$STDOUT = fopen(‘/dev/null’, “a”);$STDERR = fopen(‘/dev/null’, “a”);chdir(‘/’);umask(0);echo “這里不會(huì)輸出, ps aux | grep daemon.php 查看進(jìn)程,20s后退出” . PHP_EOL;sleep(20);
日常使用已經(jīng)注意事項(xiàng)
- php daemon.php & 這樣使用,當(dāng)關(guān)閉終端后,當(dāng)前php進(jìn)程也會(huì)同時(shí)關(guān)掉
- nohup php daemon.php > daemon.log & 終端關(guān)閉后,依然會(huì)繼續(xù)運(yùn)行
- 使用supervisor