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
PHP .Htaccess -> Pretty Url (In Reverse)
PHP Day of Week Numeric to Day of Week Text
How to Trust PHP _Destruct() Method to Be Called
Preg_Match() VS Strpos() for Match Finding
PHP Adding Custom Namespace Using Autoloader from Composer
Swift_Transportexception Connection Could Not Be Established with Host Smtp.Gmail.Com
Pdo Exception Questions - How to Catch Them
Fatal Error: Call to a Member Function Query() on Null
Parsing JavaScript (Not JSON) in PHP
Load Block Outside Magento, and Apply Current Template
How to Make Codeigniter Accept "Query String" Urls
Eloquent Parent-Child Relationship on Same Model
PHP Authentication with Multiple Domains and Subdomains
How to Send Soap Xml via Curl and PHP
Properly Calling the Database from Model in an MVC Application
Create New Product Attribute Programmatically in Woocommerce