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

8

105

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 protected]');

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?

Two answered 19/6, 2009 at 20:20 Comment(3)
NOTE: The process has to start immediately so a cron is not an option.Two
Just a quick note: Make sure the page will not be accessible by everyone (search engines/ fraudulent users) and if you are on a shared environment, the execution time of all your scripts (in particular php!) probably is limited. In any case you may want to take a look at set_time_limit/php.ini.Luellaluelle
Possible duplicate of php execute a background processMixie
C
160

How about adding.

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

shell_exec('php measurePerformance.php 47 844 [email protected] > /dev/null 2>/dev/null &');

Note this also gets rid of the stdio and stderr.

Clemenceau answered 19/6, 2009 at 20:27 Comment(9)
It works perfectly. Are there any problems / side effects of using this??Two
No. No side effects. If you sometime decide you want the stdio or stderr output of your process consider #46453Clemenceau
Question: That's just discarding the output, right? Does PHP still wait for the process to finish before continuing execution, or does it fire and forget?Stricklan
Yes discards out. Yes fire and forgetClemenceau
it is not working for the following is there any mistake I did? shell_exec('ffmpeg -f dshow -i video="Logitech HD Pro Webcam C920":audio="Rear Input (SoundMAX Integrated" -vcodec libx264 -b:v 600k -b:a 128k -f flv rtmp://127.0.0.1/live/mystream > /dev/null 2>/dev/null &');Micro
Note: > /dev/null 2>&1 & as seen in other answers is a terse form of > /dev/null 2>/dev/null & given here. This is basically saying "redirect STDERR (2) to the same place as STDOUT (&1)".Optimal
I usually get PID of running script by adding echo $! >> /tmp/pid.txt at the end of exec command but by redirecting output & error to /dev/null, no more pid file : does any of you can get PID of script launched by exec while not waiting for output ?Venosity
This answer provides a more comprehensive solution if you need to be able to check if the process is still running: https://mcmap.net/q/107492/-php-execute-a-background-processMixie
Can't get any more perfect than this. Wish I saw this a few weeks ago. ThanksIndivisible
R
29

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 &");
Reposition answered 19/6, 2009 at 20:32 Comment(3)
is it better this or shell_exec ?Melbamelborn
hi, can i run function using this shell_exec("nohup /usr/bin/php -f example.com/notifications/sendnotifications_async > /dev/null 2>&1 &");Avian
Why both nohup and the &?Sayre
B
15

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

Bouillabaisse answered 14/5, 2013 at 15:3 Comment(5)
Ops... I was waking a zombie question here, I havent realized. But this bit of information could be beneficial to others.Bouillabaisse
This has nothing to do with shell_execSayre
I'm using this for local to remote testing. On remote itself I use the shell_exec. Thx :)Cousins
While this isn't relevant to the question, it's an important side note... very useful.Chericheria
Your link appears to go to malwarePerformance
S
10

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).

Sewellyn answered 18/2, 2010 at 3:36 Comment(0)
P
9

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.

Persist answered 26/6, 2009 at 19:11 Comment(3)
It waits for child process ends. At least on WinRadiobroadcast
The backgrounding here is achieved with the help of the Windows "start" command that prefixes the exe you want to run, it wont work if you omit it, and I wouldn't expect it to work on another OS... but it DOES works for me, thanks! :-)Mccrae
this worked for me on win 10 without popping cli window: start /B php wait.php argsCousins
A
9

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
Alongshore answered 10/2, 2017 at 9:20 Comment(3)
I have no idea but it worked for me. Please anyone explain what wscript.shell is and what does it do.Cirrus
can you please explain why this line is not giving any output? ` $oExec = $WshShell->Run('C:\Users\Shreyash\Desktop\phantomjs-2.1.1-windows\bin\phantomjs.exe -f C:\xampp\htdocs\composer\test_0.js', 0, false);`Cirrus
You may have an error on test_0.js, check phantom log.Alongshore
D
1

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.

Dappled answered 19/6, 2009 at 20:23 Comment(1)
you said its a bad mojo. can you please elaborate?Karolinekaroly
S
1

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.

Selfregulated answered 19/6, 2009 at 23:58 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.