Executing command in background by shell_exec() - php

On Linux I can use shell_exec() as below to run the command in background:
shell_exec("/usr/bin/nohup curl -o /dev/null --data \"$data\" $url >/dev/null 2>&1 &");
Note that the above line doesn't wait for the result and the code will resume instantly.
How can I achieve it on windows? It's preferable to be something built-in for windows.

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

Related

php - exec() run in background [duplicate]

I have a process intensive task that I would like to run in the background.
The user clicks on a page, the PHP script runs, and finally, based on some conditions, if required, then it has to run a shell script, E.G.:
shell_exec('php measurePerformance.php 47 844 email#yahoo.com');
Currently I use shell_exec, but this requires the script to wait for an output. Is there any way to execute the command I want without waiting for it to complete?
How about adding.
"> /dev/null 2>/dev/null &"
shell_exec('php measurePerformance.php 47 844 email#yahoo.com > /dev/null 2>/dev/null &');
Note this also gets rid of the stdio and stderr.
This will execute a command and disconnect from the running process. Of course, it can be any command you want. But for a test, you can create a php file with a sleep(20) command it.
exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
You can also give your output back to the client instantly and continue processing your PHP code afterwards.
This is the method I am using for long-waiting Ajax calls which would not have any effect on client side:
ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.
You can find the detailed explanation here: http://oytun.co/response-now-process-later
On Windows 2003, to call another script without waiting, I used this:
$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg";
pclose(popen($commandString, 'r'));
This only works AFTER giving changing permissions on cmd.exe - add Read and Execute for IUSR_YOURMACHINE (I also set write to Deny).
Use PHP's popen command, e.g.:
pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));
This will create a child process and the script will excute in the background without waiting for output.
Sure, for windows you can use:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);
Note:
If you get a COM error, add the extension to your php.ini and restart apache:
[COM_DOT_NET]
extension=php_com_dotnet.dll
If it's off of a web page, I recommend generating a signal of some kind (dropping a file in a directory, perhaps) and having a cron job pick up the work that needs to be done. Otherwise, we're likely to get into the territory of using pcntl_fork() and exec() from inside an Apache process, and that's just bad mojo.
That will work but you will have to be careful not to overload your server because it will create a new process every time you call this function which will run in background. If only one concurrent call at the same time then this workaround will do the job.
If not then I would advice to run a message queue like for instance beanstalkd/gearman/amazon sqs.

php5 make a system call in the background

I am trying to create a tarball from a php5 script under Linux, and I don't really care for the output; the way I have so far found immediately is to simply
system("tar czf tarball.tgz directory/path &");
However I would like to background the process
Checking system() documentation it mentions having to redirect the output to file
However
system("tar czf tarball.tgz directory/path > /dev/null 2>&1");
doesn't help. The system() function does not take a file descriptor... what am I missing?
Testing with these:
script test.php
<pre><?php
exec("bash dodate 2>&1 /dev/null &");
system("echo done at \$(date)");
?></pre>
Script ./dodate
sleep 5
date
I go to my browser and call/refresh the page; it takes indeed 5 seconds thenprints/updates the "done" message.
Thanks
You "don't have" threads in php. One trick you can do is to do a curl request to another php that does what you want. You'll need to make sure that your curl times out pretty soon, and that the other php doesn't die when the http connection to it is closed by the curl timeout.
You can also read about the topic here: cURL Multi Threading with PHP or cURL Multi Threading?

Executing an exec() or system() in PHP and do not wait for output

I want to trigger a shell command in eider exec() or system() from PHP script but it is a task that take a while to complete, is there a way to trigger it and continue running the PHP page load without delay?
Edit: I am on CentOS 6, PHP 5.3
Depends on the OS you are using.
For linux:
pclose(popen("php somefile.php &","r"));
notice the amperstand at the end (very important).
For windows:
pclose(popen("start php.exe somefile.php","r"));
here the start keyword is important.
Hope this helps.
This doesn't answer your question directly, but you should consider doing your video conversion work in a background process with either a cron job or using a queue such as Beanstalkd.
This way you can stack up your ffmpeg work in the background without blocking your webserver.
I've had a lot of success with both methods (cron / queue) in the past.
Some other posts about background processes:
php execute a background process
Run a ffmpeg process in the background
Using ffmpeg, PHP and beanstalk
Some tools you might find useful:
http://kevin.vanzonneveld.net/techblog/article/create_daemons_in_php/
PEAR System_Daemon
Pheanstalk, a Beanstalkd library for PHP
What I do:
public function post_create()
{
ob_end_clean();
header("Connection: close");
ignore_user_abort(); // optional
ob_start();
echo "Tell ajax to gtfo!";
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush(); // Strange behaviour, will not work
flush(); // Unless both are called !
// Do processing here
}
This should work:
shell_exec("nohup yourcommand > /dev/null 2> /dev/null &");
Edit: sorry, dunno why I excluded the & to put it to bg
2> redirects STDOUT and STDERR to /dev/null.
Well use an ajax request to activate the exec part ...then continue with the other tasks

Running a PHP "exec()" in the background on Windows?

I've created a script that uses psexec to call another script which calls psexec to run a command line program of mine.
The reason for so many calls to psexec and other scripts is solely so that my PHP script doesn't have to wait for the process to finish before finishing it's output to the browser.
Is there a way I can do this without needing to use psexec? I'm having issues with psexec so I'd like to just completely remove it from my program.
I'm running Windows 2008
EDIT: I changed the title, I guess this would be a more accurate title. I found out the If a program is started with this function, in order for it to continue running in the background, the output of the program must be redirected to a file or another output stream. Failing to do so will cause PHP to hang until the execution of the program ends. on php.net's page on exec(), but wasn't sure how to do that.
Include a redirection in the command line:
exec('program.exe > NUL')
or you could modify your program to explicitly close standard output, in C this would be
CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
It is possible (the documentation doesn't say) that you might need to redirect/close both the standard output and standard error:
exec('program.exe > NUL 2> NUL')
or
CloseHandle(GetStdHandle(STD_OUTPUT_HANDLE));
CloseHandle(GetStdHandle(STD_ERROR_HANDLE));
$command = 'start /B program.exe > NUL';
pclose( popen( $command, 'r' ) );
For more info:
http://humblecontributions.blogspot.com/2012/12/how-to-run-php-process-in-background.html
Try the Windows 'start' command: http://technet.microsoft.com/en-us/library/cc770297%28WS.10%29.aspx
Using start /B has certain limitations when calling scripts that are spawning sub-processes.
The following method spawns a sub-process using PowerShell to handle such cases:
function execInBackgroundWindows($filePath, $workingDirectory, $arguments)
{
$cmd = "powershell.exe Start-Process -FilePath $filePath -WorkingDirectory $workingDirectory -ArgumentList '$arguments'";
shell_exec($cmd);
}
execInBackgroundWindows('curl.exe','c:\temp','-X POST -H "Content-Type: application/json" -d #test.json http://127.0.0.1:4000/myapp');

Is there a way to use shell_exec without waiting for the command to complete?

I have a process intensive task that I would like to run in the background.
The user clicks on a page, the PHP script runs, and finally, based on some conditions, if required, then it has to run a shell script, E.G.:
shell_exec('php measurePerformance.php 47 844 email#yahoo.com');
Currently I use shell_exec, but this requires the script to wait for an output. Is there any way to execute the command I want without waiting for it to complete?
How about adding.
"> /dev/null 2>/dev/null &"
shell_exec('php measurePerformance.php 47 844 email#yahoo.com > /dev/null 2>/dev/null &');
Note this also gets rid of the stdio and stderr.
This will execute a command and disconnect from the running process. Of course, it can be any command you want. But for a test, you can create a php file with a sleep(20) command it.
exec("nohup /usr/bin/php -f sleep.php > /dev/null 2>&1 &");
You can also give your output back to the client instantly and continue processing your PHP code afterwards.
This is the method I am using for long-waiting Ajax calls which would not have any effect on client side:
ob_end_clean();
ignore_user_abort();
ob_start();
header("Connection: close");
echo json_encode($out);
header("Content-Length: " . ob_get_length());
ob_end_flush();
flush();
// execute your command here. client will not wait for response, it already has one above.
You can find the detailed explanation here: http://oytun.co/response-now-process-later
On Windows 2003, to call another script without waiting, I used this:
$commandString = "start /b c:\\php\\php.EXE C:\\Inetpub\\wwwroot\\mysite.com\\phpforktest.php --passmsg=$testmsg";
pclose(popen($commandString, 'r'));
This only works AFTER giving changing permissions on cmd.exe - add Read and Execute for IUSR_YOURMACHINE (I also set write to Deny).
Use PHP's popen command, e.g.:
pclose(popen("start c:\wamp\bin\php.exe c:\wamp\www\script.php","r"));
This will create a child process and the script will excute in the background without waiting for output.
Sure, for windows you can use:
$WshShell = new COM("WScript.Shell");
$oExec = $WshShell->Run("C:/path/to/php-win.exe -f C:/path/to/script.php", 0, false);
Note:
If you get a COM error, add the extension to your php.ini and restart apache:
[COM_DOT_NET]
extension=php_com_dotnet.dll
If it's off of a web page, I recommend generating a signal of some kind (dropping a file in a directory, perhaps) and having a cron job pick up the work that needs to be done. Otherwise, we're likely to get into the territory of using pcntl_fork() and exec() from inside an Apache process, and that's just bad mojo.
That will work but you will have to be careful not to overload your server because it will create a new process every time you call this function which will run in background. If only one concurrent call at the same time then this workaround will do the job.
If not then I would advice to run a message queue like for instance beanstalkd/gearman/amazon sqs.

Categories