Asynchronous Shell Exec in PHP

Asynchronous shell exec in PHP

If it "doesn't care about the output", couldn't the exec to the script be called with the & to background the process?

EDIT - incorporating what @AdamTheHut commented to this post, you can add this to a call to exec:

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

That will redirect both stdio (first >) and stderr (2>) to /dev/null and run in the background.

There are other ways to do the same thing, but this is the simplest to read.


An alternative to the above double-redirect:

" &> /dev/null &"

Run PHP exec() asynchronously, but check for completion?

You should start an asynchronous command line php script that encodes both videos and then sends an email :

upload.php :

exec('/usr/bin/php -f encode_files.php > /dev/null 2>/dev/null &"');
echo "Files will be encoded, come back later !";

encode_files.php

exec('avconv ...'); // Synchronously ! Without > /dev/null etc ...
exec('avconv ...'); // webm ...

mail('user@user.com', 'Encoding complete ! ', 'Great ! ');

I left the call as "bash -c exec ..." but i think there are shorter ways to call php scripts asynchronously :
Asynchronous shell exec in PHP
You can even pass params (like the user/video id, ...)

$cmd = 'nohup /usr/bin/php -f /path/to/php/file.php action=generate var1_id=23 var2_id=35 gen_id=535 > /path/to/log/file.log & printf "%u" $!';
$pid = shell_exec($cmd);

PHP Execute shell command asynchronously and retrieve live output

I've solved the problem by piping the output STDIN to a temporary file and then reading from it.

Here's my

Implementation

class ExecAsync {

public function __construct($cmd) {
$this->cmd = $cmd;
$this->cacheFile = ".cache-pipe-".uniqid();
$this->lineNumber = 0;
}

public function getLine() {
$file = new SplFileObject($this->cacheFile);
$file->seek($this->lineNumber);
if($file->valid())
{
$this->lineNumber++;
$current = $file->current();
return $current;
} else
return NULL;
}

public function hasFinished() {
if(file_exists(".status-".$this->cacheFile) ||
(!file_exists(".status-".$this->cacheFile) && !file_exists($this->cacheFile)))
{
unlink($this->cacheFile);
unlink(".status-".$this->cacheFile);
$this->lineNumber = 0;
return TRUE;
} else
return FALSE;
}

public function run() {
if($this->cmd) {
$out = exec('{ '.$this->cmd." > ".$this->cacheFile." && echo finished > .status-".$this->cacheFile.";} > /dev/null 2>/dev/null &");
}
}
}

Usage

$command = new ExecAsync("command to execute");
//run the command
$command->run();
/*We want to read from the command output as long as
*there are still lines left to read
*and the command hasn't finished yet

*if getLine returns NULL it means that we have caught up
*and there are no more lines left to read
*/
while(($line = $command->getLine()) || !$command->hasFinished())
{
if($line !== NULL)
{
echo $line."\n";
flush();
} else
{
usleep(10);
}
}

Asynchronous call to shell_exec() php

$cmd = $command;

$descriptorspec = array(
0 => array("pipe", "r"), // stdin is a pipe that the child will read from
1 => array("pipe", "w"), // stdout is a pipe that the child will write to
2 => array("pipe", "w") // stderr is a pipe that the child will write to
);
flush();
$process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());
echo "<pre>";
if (is_resource($process)) {
while ($s = fgets($pipes[1])) {
print $s;
flush();
}
}
echo "</pre>";

The Code above Worked perfectly for me, This is copied from another answer I can no longer find. If you put a ping 127.0.0.1 in the $command it works exactly like it does in a terminal.

exec() should be asynchronous, but it isn't

I have the same problem, years ago with videos. PHP is not async. I suggest to you use React PHP (http://reactphp.org/) or create JobQueue and/or Cron task lists to process this after. You can create the video and upload, on show to user the video, show message, "Rendering" and create a sample thumbnail to videos when not created the thumbnail to him.

I founded this example using Yii to JobQueue, but search better after. https://github.com/yiisoft/yii2-queue

How to execute shell commands synchronously in PHP

PHP exec will wait until the execution of the called program is finished, before processing the next line, unless you use & at the end of the string to run the program in background.

Asynchronous popen exec in PHP on Windows

Eventually I was able to simply get around this problem by not using popen or exec at all, it seems like those may be best avoided when using PHP on a Windows platform - if you are trying to create an asynchronous script call that is. Instead I resorted to the Windows COM object support in PHP.

$handle = new COM('WScript.Shell');
$handle->Run($command, 0, false);

This starts the process in the background (hides window/does not open a new window) and executes it asynchronously - i.e. does not wait for it to finish.

Included here is the documentation page for WScript.Shell which gives the official description of the effect(s) of the parameters passed. Although I did not stop to benchmark it, I will say that anecdotally it feels that his process now runs more quickly than it used to when I was trying to use exec/popen/etc.



Related Topics



Leave a reply



Submit