php非阻塞执行系统命令

大家都知道php调用系统命令常用的主要有以下几种方法:

exec(), system(),passthru(), shell_exec()

这几个函数的用法在此不做说明,有需要的请查阅php相关手册。

今天主要说的是:非阻塞的方式执行系统命令。

那么,首先什么是非阻塞呢?

要说非阻塞,我们先说一下什么是阻塞,下面先看一个例子:

a.php
<?
    echo "begin:<br>";
    echo exec('php b.php');    //我这里为了方便测试是拿php直接执行一个程序当做系统命令,你可以执行其他命令,比如一个shell脚本,或者系统的一些其他程序,如打包tar -cvf xxx。
    echo "end";
?>

b.php
<?
    $file = fopen("a.txt", "a+");
    for($i=0;$i<100;$i++){
        fwrite($file,"line".$i." Hello World. Testing!\r\n");
        sleep(1);
    }
    fclose($file);
    echo "ok<br>";
?>

我们在浏览器中访问上面的a.php后,发现浏览器一直转啊转,一直过了大概100秒才输出最后的结果,结果是:

begin

ok

end

结果说明a.php在执行exec()函数的时候一直在等待b.php执行完才返回,这就是阻塞。

我们在实际项目中,如果用户请求一个非常耗时的任务,比如耗时的批处理任务、文件打包或者大文件压缩等等,这时候如果采用阻塞方式,那么用户就需要在浏览器一直等,直到任务执行完返回才能干别的事。这很明显不是一个好的设计。那么有没有办法做到非阻塞,即,不用等待耗时任务执行完就返回,而且返回结果后后台还得把活干完?

答案是有的,请看下面对a.php的修改

<?
    echo "begin:<br>";
    echo exec('php b.php'.' > /dev/null &');
    echo "end"; 
?>

没错照上面那样修改后,就可以了,那

> /dev/null & 是什么意思呢?
> 这个符号,熟悉命令行的都应该清楚是指输出
/div/null 这个在linux上是指空设备,是一个特殊的设备文件,我们可以认为是将输出信息丢弃。
& 这个符号,熟悉命令行的应该也清楚,是指后台执行

没错照上面那样修改完后,就可以实现php非阻塞方式的调用系统命令了。