How to Execute Shell Commands Synchronously in PHP

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 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 &"

How to synchronously spawn another PHP script from within a PHP script?

I'm don't understand your concern about "when the script is interpreted" vs "when the script is executed"? I have a number of scripts that use a variable name for the script to be included and make that decision right before executing the include statement. $result = include($script_name) will work fine and the decision about which script to include can be made at run time.

The way you describe the problem does not seem to indicate that you want to "launch" another process, but I could be wrong.

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 exec() execute last command only?

exec returns the last line from the result of the command. You have to use output argument. If the output argument is present, then the specified array will be filled with every line of output from the command.

exec("id;ls", $output);
var_dump($output);

Executing command in background by shell_exec()

I'd check out the Symfony Process component for this use case. It provides methods for executing synchronously and asynchronously. It can be easily installed through Composer, but it requires PHP 7.1 at least.

The documentation can be found here: https://symfony.com/doc/current/components/process.html

An example for your use case could look like this:

$process = new Process(['curl', '--data', $data, $url]);
$process->start();

Note that I omitted the -o option because the output of the sub process won't show up unless you request it explicitly.
A quick browse yielded some posts that said that the start() method blocks on Windows but it seems that a patch has already been implemented and merged: https://github.com/symfony/symfony/pull/10420

EDIT: If you don't want to use a library, you can use a combination of popen(), pclose() and the Windows tool start:

pclose(popen('start /B curl --data "'.$data.'" '.$url, 'r'));

This runs the program in background without opening a window and immediately returns.

EDIT 2: Source for the trick with start /B: http://php.net/manual/en/function.exec.php#86329

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.



Related Topics



Leave a reply



Submit