Asynchronous shell exec in PHP

2018-12-31 04:13发布

I've got a PHP script that needs to invoke a shell script but doesn't care at all about the output. The shell script makes a number of SOAP calls and is slow to complete, so I don't want to slow down the PHP request while it waits for a reply. In fact, the PHP request should be able to exit without terminating the shell process.

I've looked into the various exec(), shell_exec(), pcntl_fork(), etc. functions, but none of them seem to offer exactly what I want. (Or, if they do, it's not clear to me how.) Any suggestions?

13条回答
十年一品温如言
2楼-- · 2018-12-31 04:49

the right way(!) to do it is to

  1. fork()
  2. setsid()
  3. execve()

fork forks, setsid tell the current process to become a master one (no parent), execve tell the calling process to be replaced by the called one. so that the parent can quit without affecting the child.

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

 // parent's stuff
 exit();
查看更多
公子世无双
3楼-- · 2018-12-31 04:53

I used at for this, as it is really starting an independent process.

<?php
    `echo "the command"|at now`;
?>
查看更多
裙下三千臣
4楼-- · 2018-12-31 04:57

To all Windows users: I found a good way to run an asynchronous PHP script (actually it works with almost everything).

It's based on popen() and pclose() commands. And works well both on Windows and Unix.

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

Original code from: http://php.net/manual/en/function.exec.php#86329

查看更多
栀子花@的思念
5楼-- · 2018-12-31 04:57

The only way that I found that truly worked for me was:

shell_exec('./myscript.php | at now & disown')
查看更多
像晚风撩人
6楼-- · 2018-12-31 04:57

without use queue, you can use the proc_open() like this:

    $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);
查看更多
几人难应
7楼-- · 2018-12-31 05:01

On linux you can do the following:

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

This will execute the command at the command prompty and then just return the PID, which you can check for > 0 to ensure it worked.

This question is similar: Does PHP have threading?

查看更多
登录 后发表回答