其一
/*
* php 进程管理
*/
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
$STDIN = fopen('/dev/null', 'r');
$STDOUT = fopen('application.log', 'wb');
$STDERR = fopen('error.log', 'wb');
echo '父进程:'.posix_getpid()."\r\n";
$pid = pcntl_fork();
//父进程和子进程都会执行下面代码
echo '创建了子进程:'.$pid . "\r\n";
if ($pid == -1) {
//错误处理:创建子进程失败时返回-1.
die('could not fork');
} else if ($pid > 0) {
//父进程会得到子进程号,所以这里是父进程执行的逻辑
//pcntl_wait($status); //等待子进程中断,防止子进程成为僵尸进程。
echo '结束父进程'."\r\n";
exit(0);
}
//子进程得到的$pid为0, 所以这里是子进程执行的逻辑。
$sid = posix_setsid(); //Make the current process a session leader
if($sid < 0){
//-1 创建失败
exit(1);
}
while(true){
sleep(1);
echo '守护进程在运行,时间:'.date('Y-m-d H:i:s')."\r\n";
}
其二
<?php
$pid = pcntl_fork();
if ($pid == -1)
{
throw new Exception('fork子进程失败');
}
elseif ($pid > 0)
{
//父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端
exit(0);
}
// 最重要的一步,让该进程脱离之前的会话,终端,进程组的控制
posix_setsid();
// 修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
// 这里重定向了根目录。在后面可以再次重定向指定文件目录
chdir('/');
/*
* 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免
* 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。
*/
$pid = pcntl_fork();
if ($pid == -1)
{
throw new Exception('fork子进程失败');
}
elseif ($pid > 0)
{
// 再一次退出父进程,子进程成为最终的守护进程
exit(0);
}
// 由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
/*
* 处理业务代码
*/
while(TRUE)
{
file_put_contents('log.txt', time().PHP_EOL, FILE_APPEND);
sleep(5);
}
优化后
<?php
Class Daemon{
/**
* 初始化一个守护进程
* @throws Exception
*/
public function init(){
//创建一个子进程
$pid = pcntl_fork();
if ($pid == -1) {
throw new Exception('fork子进程失败');
} elseif ($pid > 0) {
//父进程退出,子进程变成孤儿进程被1号进程收养,进程脱离终端
exit(0);
}
//创建一个新的会话,脱离终端控制,更改子进程为组长进程
$sid = posix_setsid();
if ($sid == -1) {
throw new Exception('setsid fail');
}
//修改当前进程的工作目录,由于子进程会继承父进程的工作目录,修改工作目录以释放对父进程工作目录的占用。
chdir('/');
/**
* 通过上一步,我们创建了一个新的会话组长,进程组长,且脱离了终端,但是会话组长可以申请重新打开一个终端,为了避免
* 这种情况,我们再次创建一个子进程,并退出当前进程,这样运行的进程就不再是会话组长。
*/
$pid = pcntl_fork();
if ($pid == -1) {
throw new Exception('fork子进程失败');
} elseif ($pid > 0) {
//再一次退出父进程,子进程成为最终的守护进程
exit(0);
}
//由于守护进程用不到标准输入输出,关闭标准输入,输出,错误输出描述符
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
}
}
$daemon = new Daemon();
$daemon->init();
//处理业务代码
while(true) {
file_put_contents('/usr/local/src/log.txt', time().PHP_EOL, FILE_APPEND);
sleep(5);
}
网友评论