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
File_Get_Contents(): Ssl Operation Failed With Code 1, Failed to Enable Crypto
How to List Has Same Id Data With While Loop in PHP
How to Output a Utf-8 CSV in PHP That Excel Will Read Properly
How to Read If a Checkbox Is Checked in PHP
Doctrine2: Best Way to Handle Many-to-many With Extra Columns in Reference Table
How to Get the Cookies from a PHP Curl into a Variable
What Does a \ (Backslash) Do in PHP (5.3+)
How to Change the Session Timeout in PHP
Pdoexception Sqlstate[Hy000] [2002] No Such File or Directory
How to Convert Xml into Array in PHP
Download File to Server from Url
Convert Seconds to Hour:Minute:Second
"Keep Me Logged In" - the Best Approach
How to Create Multiple Where Clause Query Using Laravel Eloquent