监控程序--PHP后台守护进程

        在命令后面加上 & 符号, 可以让启动的进程转到后台运行,而不占用控制台,控制台还可以再运行其他命令

        用 & 方式来启动该进程

[root@localhost php]# php deadloop.php &
[1] 3454
[root@localhost php]# ps aux | grep 3454
root      3454  0.0  0.8 284544  8452 pts/0    T    18:06   0:00 php deadloop.php
root      3456  0.0  0.0 103316   896 pts/0    S+   18:08   0:00 grep 3454

[1]+  Stopped                 php deadloop.php
[root@localhost php]#

        可以看到该进程并未占用控制台,控制台还可以运行其他命令,这时我们还可以通过 fg 命令让进程恢复到普通占用控制台的模式

[root@localhost php]# fg
php deadloop.php
1470996682
1470996685
1470996688
1470996691

        在命令之前加上 nohup ,启动的进程将会忽略linux的挂起信号 (SIGHUP),那什么情况下会触发linux下SIGHUP信号呢,以下内容摘自百度百科:

SIGHUP会在以下3种情况下被发送给相应的进程:
1、终端关闭时,该信号被发送到session首进程以及作为job提交的进程(即用 & 符号提交的进程)
2、session首进程退出时,该信号被发送到该session中的前台进程组中的每一个进程
3、若父进程退出导致进程组成为孤儿进程组,且该进程组中有进程处于停止状态(收到SIGSTOP或SIGTSTP信号),该信号会被发送到该进
程组中的每一个进程。

        结合 1和2 我们知道,不管是否以 & (job方式)启动的进程,关闭终端时都会收到  SIGHUP 信号 ,那么进程收到 SIGHUP 信号会如何处理呢,看同样是摘自百度百科的一句话

系统对SIGHUP信号的默认处理是终止收到该信号的进程。所以若程序中没有捕捉该信号,当收到该信号时,进程就会退出。

        也就是说关闭终端进程会收到SIGHUP信号,而该信号的默认处理方式就是结束掉该进程,当然 我们也可以自己捕获处理该信号,或者忽略它,例如以下代码

<?php
pcntl_signal(SIGHUP, function(){
    //  这地方处理信号的方式我们只是简单的写入一句日志到文件中
    file_put_contents('logs.txt', 'pid : ' . posix_getpid() . ' receive SIGHUP 信号' . PHP_EOL);
});
        
while(1) {
    sleep(10);
    pcntl_signal_dispatch();
}

        我们在命令行运行该例程,然后直接关闭掉该shell终端窗口,然后重新打开一个终端查看这个进程是否还在运行:

[root@localhost php]# ps -ef | grep deadloop.php 
root     16112     1  0 17:20 ?        00:00:00 php deadloop.php
root     16138 16115  0 17:24 pts/4    00:00:00 grep deadloop.php
[root@localhost php]# cat logs.txt 
pid : 16112 receive SIGHUP 信号

        可以看到 deadloop.php 仍在运行,而其父进程变成了 init 进程 (由于其原本父进程退出了从而被init进程收养),从写到的文件内容也可以看到 关闭终端进程收到了 SIGHUP 信号。其实我们不必这么麻烦,只需要使用linux提供给我们的nohup命令,但我们使用nohup启动进程时,进程会忽略收到的SIGHUP信号,也就不会退出了,首先去掉刚才的信号处理代码。然后nohup 运行。

[root@localhost php]# nohup php deadloop.php 
nohup: 忽略输入并把输出追加到"nohup.out"

        并且nohup默认会把程序的输出重定向到当前目录下的nohup.out文件,如果没有可写权限,则写入 $homepath/nohup.out

[root@localhost ~]# ps -ef | grep 3554
root      3554  3497  0 19:09 pts/0    00:00:00 php deadloop.php
root      3575  3557  0 19:10 pts/1    00:00:00 grep 3554
[root@localhost ~]# ps -ef | grep 3554
root      3554     1  0 19:09 ?        00:00:00 php deadloop.php
root      3577  3557  0 19:10 pts/1    00:00:00 grep 3554
[root@localhost ~]#

        结论: 所以当我们组合 nohup 和 & 两种方式时,启动的进程不会占用控制台,也不依赖控制台,控制台关闭之后进程被1号进程收养,成为孤儿进程,这就和守护进程的机制非常类似了

[root@localhost php]# nohup php deadloop.php >logs.txt 2>error.txt &
[1] 3612
[root@localhost php]# ps -ef |grep 3612
root      3612  3557  0 19:18 pts/1    00:00:00 php deadloop.php
root      3617  3557  0 19:19 pts/1    00:00:00 grep 3612
[root@localhost php]#

        其中 >logs.txt 重定向标准输出,2>error.txt 重定向标准错误输出。

        

具体实例:

        首先查看我们的定时任务服务是否已经安装,如果没有安装,执行:

[root@localhost ~]# yum install crontabs

        然后,查看我们的服务是否启动:

[root@localhost ~]# systemctl status  crond.service        查看定时任务服务是否状态

        查看、编辑定时任务、查看定时任务邮件

编辑定时任务:
[root@localhost ~]# crontab -e
*/1 * * * * /crontab.sh

查看当前定时任务:    
[root@localhost ~]# crontab -l
*/1 * * * *  /usr/local/php7/bin/php  /Daemon.php

        新建监控守护进程文件Daemon.php

[root@localhost /]# vim Daemon.php

<?php
$output = `ps awx |grep demo2.php`;
$opter  = "/demo2.php";
$flag   =  strpos($output , $opter);
if($output && false === $flag)
{
    echo "[" . date('Y-m-d H:i:s') . "] $opter \r\n";
    exec("nohup  /usr/local/php7/bin/php $opter >> /demo2.log 2>&1 &");
}

var_dump($flag);
var_dump($output);

        设置监控文件为可执行文件:

[root@localhost /]# chmod +x Daemon.php

        编辑 demo2.php 文件

[root@localhost /]# vim demo2.php 

<?php
file_put_contents('/output.log', date('Y-m-d H:i:s').'哈哈哈'."\r\n", FILE_APPEND);

echo date('Y-m-d H:i:s').PHP_EOL;

        

        查看监控程序打印日志:

[root@localhost /]# tail -f demo2.log

        冷暖自知一抹茶ck

        查看执行文件输出结果:

[root@localhost /]# tail -f output.log

        冷暖自知一抹茶ck



使用 pcntl_*系列函数实现守护进程:监控程序--PHP后台守护进程(二)


冷暖自知一抹茶ck
请先登录后发表评论
  • 最新评论
  • 总共0条评论