源码 signal_fun.php
<?php
// 设置信号处理函数
function signal_handler($signo) {
switch ($signo) {
case SIGTERM:
// 处理SIGTERM信号
tlog("Caught SIGTERM...exit...\n");
exit;
break;
case SIGHUP:
//处理SIGHUP信号
tlog("Caught SIGHUP...\n");
break;
case SIGUSR1:
tlog("Caught SIGUSR1...\n");
break;
default:
// 处理所有其他信号
}
}
// 写日志
function tlog($message, $print=1) {
$message = posix_getpid() . '_' . $message . "\n";
if ($print) {
echo $message;
} else {
error_log(posix_getpid() . '_' . $message . "\n", 3, '/var/www/log.log');
}
}
function _system($script) {
return system("/usr/local/php/bin/php /var/www/{$script} >> /var/www/system.log");
}
源码 main.php
<?php
include_once './signal_fun.php';
tlog('im start run');
declare(ticks=1);
// 开启一个信号监控
pcntl_signal(SIGTERM, 'signal_handler');
$myids = array();
while(1) {
for ($i = 0; $i < 5; ++$i) {
$mypid =pcntl_fork(); // 开启一个子进程,子进程和父进程同时从此处向下执行
if ($mypid < 0) { // 子进程启动失败
tlog('fork error!');
} elseif ($mypid == 0) { // 子进程中,读到的进程id为0
tlog('im child!');
sleep(1000); // 子进程挂起
exit;
} else { // 父进程读到子进程的pid
$myids[] = $mypid;
sleep(1);
}
}
sleep(10);
if ($myids) {
foreach ($myids as $key => $pid) {
tlog('kill '. $pid);
posix_kill($pid, SIGTERM); // 传递信号,kill 子进程
unset($myids);
sleep(2);
}
}
}
完整的执行结果是这样
30834_im start run
30835_im child!
30836_im child!
30837_im child!
30838_im child!
30839_im child!
30834_kill 30835
30835_Caught SIGTERM...exit...
30834_kill 30836
30836_Caught SIGTERM...exit...
30834_kill 30837
30837_Caught SIGTERM...exit...
30834_kill 30838
30838_Caught SIGTERM...exit...
30834_kill 30839
30839_Caught SIGTERM...exit...
30860_im child!
30863_im child!
30866_im child!
30869_im child!
30872_im child!
先开启5个子进程,再杀死5个子进程,再开启...以此循环。
我想验证一下父进程关闭后,因为在main.php中声明了declare(ticks=1); 所以应该子进程时间到了之后关闭后,会自动去产生信号SIGTERM,由此也可以出现 30839_Caught SIGTERM...exit...这种提示,但是现在出现的问题是这样
# php main.php
2356_im start run
2357_im child!
2358_im child!
2359_im child!
2360_im child!
2361_im child!
^C
# kill -9 2357
-bash: kill: (2357) - 没有那个进程
# kill -9 2358
-bash: kill: (2358) - 没有那个进程
# kill -9 2359
-bash: kill: (2359) - 没有那个进程
# kill -9 2360
-bash: kill: (2360) - 没有那个进程
# kill -9 2361
-bash: kill: (2361) - 没有那个进程
ctrl+c关闭父进程之后,子进程没有了...
自己刚才试了试,现在把所有的过程粘贴到这边,希望后面遇到问题的有所启发
结论:使用ctrl c干掉父进程 那么一个进程组的子进程都会被干掉
使用kill -9 pid干掉父进程 子进程还存活着,说明这两个操作有本质上的不同
补充一点 刚才@walkor 说的 ctrl c的时候会向所有该程序的进程包括子进程发送SIGINT信号的