PHP中的asynchronousshell exec

我有一个PHP脚本,需要调用一个shell脚本,但不关心输出。 shell脚本进行了大量的SOAP调用,并且执行起来很慢,所以我不想在等待回复时减慢PHP请求的速度。 实际上,PHP请求应该能够在不终止shell进程的情况下退出。

我研究了各种exec()shell_exec()pcntl_fork()等函数,但是他们都没有提供我想要的东西。 (或者,如果他们这样做,我不清楚如何。)有什么build议吗?

如果它“不关心输出”,那么可以用&来调用脚本的执行到后台进程吗?

编辑 – 纳入什么@ AdamTheHut评论到这个职位,你可以添加到调用exec

 " > /dev/null 2>/dev/null &" 

这会将stdio (第一> )和stderr2> )redirect到/dev/null并在后台运行。

还有其他方法可以做同样的事情,但这是最简单的方法。


上述双重redirect的替代方法:

 " &> /dev/null &" 

我用这个,因为它真的开始一个独立的过程。

 <?php `echo "the command"|at now`; ?> 

在Linux上,您可以执行以下操作:

 $cmd = 'nohup nice -n 10 php -f php/file.php > log/file.log & printf "%u" $!'; $pid = shell_exec($cmd); 

这将执行命令prompty然后只是返回PID,你可以检查> 0,以确保它的工作。

这个问题是类似的: PHP是否有线程?

php-execute-a-background-process有一些很好的build议。 我觉得我很好,但我有点偏见:)

对于所有Windows用户:我find了一个运行asynchronousPHP脚本的好方法(实际上它几乎适用于所有的情况)。

它基于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

在Linux中,可以通过在命令末尾添加&符号来在新的独立线程中启动进程

 mycommand -someparam somevalue & 

在Windows中,您可以使用“启动”DOS命令

 start mycommand -someparam somevalue 

正确的方法(!)来做到这一点

  1. 叉子()
  2. setsid()
  3. 的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(); 

我用这个…

 /** * Asynchronously execute/include a PHP file. Does not record the output of the file anywhere. * Relies on the PHP_PATH config constant. * * @param string $filename file to execute * @param string $options (optional) arguments to pass to file via the command line */ function asyncInclude($filename, $options = '') { exec(PHP_PATH . " -f {$filename} {$options} >> /dev/null &"); } 

(其中PHP_PATH是一个像define('PHP_PATH', '/opt/bin/php5')或类似的define('PHP_PATH', '/opt/bin/php5')的const)

它通过命令行传递参数。 要在PHP中阅读它们,请参阅argv 。

我发现真正为我工作的唯一方法是:

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

使用一个名为fifo。

 #!/bin/sh mkfifo trigger while true; do read < trigger long_running_task done 

然后,只要你想开始长时间运行的任务,只需写一个换行符(非阻塞触发器文件。

只要你的input小于PIPE_BUF并且它是一个单独的write()操作,你可以将参数写入fifo,并在脚本中显示为$REPLY

您也可以将PHP脚本作为守护进程cronjob运行#!/usr/bin/php -q

没有使用队列,你可以像这样使用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); 

我也发现Symfony过程组件对此很有用。

 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仓库中是如何工作的。