我有一个PHP脚本,需要调用shell脚本,但根本不关心输出。shell脚本执行了许多SOAP调用,完成起来很慢,因此我不想在PHP请求等待应答时降低它的速度。事实上,PHP请求应该能够在不终止shell进程的情况下退出。

我已经研究了各种exec()、shell_exec()、pcntl_fork()等函数,但它们似乎都不能提供我想要的东西。(或者,即使他们这样做,我也不清楚是如何做到的。)有什么建议吗?


当前回答

做这件事的正确方法是

叉() 塞西德() execve()

Fork Fork, setsid告诉当前进程成为主进程(没有父进程),execve告诉调用进程被被调用进程取代。这样父母可以在不影响孩子的情况下退出。

 $pid=pcntl_fork();
 if($pid==0)
 {
   posix_setsid();
   pcntl_exec($cmd,$args,$_ENV);
   // child becomes the standalone detached process
 }

 // parent's stuff
 exit();

其他回答

如果没有使用队列,你可以像这样使用proc_open():

    $descriptorspec = array(
        0 => array("pipe", "r"),
        1 => array("pipe", "w"),
        2 => array("pipe", "w")    //here curaengine log all the info into stderror
    );
    $command = 'ping stackoverflow.com';
    $process = proc_open($command, $descriptorspec, $pipes);

对所有Windows用户:我发现了一个运行异步PHP脚本的好方法(实际上它几乎适用于所有东西)。

它基于popen()和pclose()命令。并且在Windows和Unix上都能很好地工作。

function execInBackground($cmd) {
    if (substr(php_uname(), 0, 7) == "Windows"){
        pclose(popen("start /B ". $cmd, "r")); 
    }
    else {
        exec($cmd . " > /dev/null &");  
    }
} 

原始代码来自:http://php.net/manual/en/function.exec.php#86329

我还发现Symfony Process Component在这方面很有用。

use Symfony\Component\Process\Process;

$process = new Process('ls -lsa');
// ... run process in background
$process->start();

// ... do other things

// ... if you need to wait
$process->wait();

// ... do things after the process has finished

在GitHub回购中查看它是如何工作的。

我发现唯一对我有效的方法是:

shell_exec('./myscript.php | at now & disown')

您也可以运行PHP脚本作为daemon或cronjob: #!/usr/bin/php q