pic1

使用PHP来写守护进程

既然PHP有命令行,可以做的事情就非常多了。不过要用它写守护进程?也是可以的。用pcntl系列函数就可以完成很多事情了。为什么叫pcntl,大约应该叫process-control的意思吧,进程控制。

进程处理,就是fork,然后信号处理的一些事情。fork和信号估计可以单独写一章了。简单地讲fork就是把进程复制一份出来,然后在程序里可以控制主进程做什么,子进程做什么。信号就是一个进程往另一个进程发送的消息。

今天发现一个好东西,Clio。

Clio is a lightweight utility and helper classes for CLI applications.
It provides colored output, prompts, confirmation inputs, selections, background processes, as well as a way to start and stop daemons.

可以用composer安装,然后就可以很方便地使用了。集成了pcntl的函数,用起来小爽的。它有两个类,一个类可以帮我们做守护进程,另一个类就是控制台的操作,比如在控制台输出彩色文本有没有,还可以使用控制台输入有没有!

composer.json中添加下面这段,然后composer update就好了。

{
    "require": {
        "clio/clio": "*"
    }
}

好了,现在讲守护进程这块。代码看起来就是这样的。

<?php
use Clio\Daemon;
if (Daemon::isRunning('/path/to/process.pid')) {
    echo "daemon is already running.\n";
} else {
    Daemon::work(array(
            'pid'    => '/path/to/process.pid', // required
            'stdin'  => '/dev/null',            // defaults to /dev/null
            'stdout' => '/path/to/stdout.txt',  // defaults to /dev/null
            'stderr' => '/path/to/stderr.txt',  // defaults to php://stdout
        ),
        function($stdin, $stdout, $stderr) { // these parameters are optional
            while (true) {
                // do whatever it is daemons do
                sleep(1); // sleep is good for you
            }
        }
    );
    echo "daemon is now running.\n";
}

它就会自动把进程号写到process.pid文件里。

要把进程停下来的话。

<?php
use Clio\Daemon;

if (Daemon::isRunning('/path/to/process.pid')) {
    echo "killing running daemon ...\n";
    if (Daemon::kill('/path/to/process.pid')) {
        echo "daemon killed.\n";
    } else {
        echo "failed killing daemon.\n";
    }
} else {
    echo "nothing to kill.\n";
}

有没有很爽?

在守护进程里的sleep是必须的。不然cpu很快被跑满的。如果嫌sleep太久,可以用usleep,是微秒级的。

实际使用中,还是要在最外面加一个异常捕捉的。还有就是处理一下while循环,保证在kill的时候一个逻辑能全部执行完毕之后再kill掉。

Copyright © 2015. All Rights Reserved.

发表评论

电子邮件地址不会被公开。 必填项已用*标注