PHP学习之信号

通过几个简单的例子,来帮助理解php的信号系统

singnal_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");
}


例1:

功能:父进程先开启子进程,然后通过信号传递,关闭子进程,一直循环

<?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[$key]);
			
			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个子进程,再开启...以此循环。

例2

功能:在后台挂起需要执行的脚本,任意脚本退出之后会马上重新开启一个

<?php
include_once './signal_fun.php';

$pids = array();		// 子进程pid容器
$end_pid = 0;			// 当前接收到的结束进程的pid
while(1) {
	
	for ($i = 1; $i <= 3; $i++) {
		if ($end_pid) {
			if ($i != current(array_diff(array(1,2,3), $pids))) {		// 过滤掉正在运行的脚本
				continue;
			}
		}
		
		$mypid = pcntl_fork();
		if ($mypid < 0) {
			tlog('fork error!');
		} elseif ($mypid == 0) {	// child
			_system('t'.$i.'.php');	// 挂起脚本
			
			exit;
		} else {					// parent
			$pids[$mypid] = $i;		// 将正在运行的脚本的编号与子进程id压入数组
		}
	}
	
	$end_pid = pcntl_wait($status);		// 挂起父进程,等待接收子进程结束的信号
	tlog('----接收到子进程-----' . $end_pid . '====运行结束');
	unset($pids[$end_pid]);
}

父进程debug信息

32101_----接收到子进程-----32104====运行结束
32101_----接收到子进程-----32106====运行结束
32101_----接收到子进程-----32102====运行结束
32101_----接收到子进程-----32111====运行结束
32101_----接收到子进程-----32114====运行结束

看看日志log信息

tail -f /var/www/system.log

32107_t1 runnion
32109_t2 runnion
32110_t3 runnion
32113_t2 runnion
32116_t3 runnion
32119_t1 runnion
32122_t2 runnion
32125_t3 runnion
32128_t2 runnion
32131_t3 runnion
32134_t2 runnion
32137_t3 runnion
32140_t1 runnion
32143_t3 runnion
32146_t2 runnion
32149_t3 runnion
32152_t2 runnion
32155_t3 runnion

可以看到一直在开启这3个脚本。


再来看看进程信息

[root@192.168.64.90 /var/www]# ps -ef | grep signal3.php 
root     32101 30341  0 14:44 pts/0    00:00:00 php signal3.php
root     32346 32101  0 14:46 pts/0    00:00:00 php signal3.php
root     32349 32101  0 14:46 pts/0    00:00:00 php signal3.php
root     32352 32101  0 14:46 pts/0    00:00:00 php signal3.php


可以看出父进程开启了3个子进程,用于运行对应的脚本

[root@192.168.64.90 /var/www]# ps -ef | grep /var/www
root     32463 32462  0 14:47 pts/0    00:00:00 sh -c /usr/local/php/bin/php /var/www/t1.php >> /var/www/system.log
root     32464 32463  0 14:47 pts/0    00:00:00 /usr/local/php/bin/php /var/www/t1.php
root     32477 32476  0 14:47 pts/0    00:00:00 sh -c /usr/local/php/bin/php /var/www/t2.php >> /var/www/system.log
root     32478 32477  0 14:47 pts/0    00:00:00 /usr/local/php/bin/php /var/www/t2.php
root     32480 32479  0 14:47 pts/0    00:00:00 sh -c /usr/local/php/bin/php /var/www/t3.php >> /var/www/system.log
root     32481 32480  0 14:47 pts/0    00:00:00 /usr/local/php/bin/php /var/www/t3.php


可以看到这3个脚本一直在后台运行着,kill其中一个之后,父进程like又会重新开启一个新的进程,这在需要运行daemon脚本时非常有用

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值