91

I have a command I want to run, but I do not want PHP to sit and wait for the result.

<?php
echo "Starting Script";
exec('run_baby_run');
echo "Thanks, Script is running in background";
?>

Is it possible to have PHP not wait for the result.. i.e. just kick it off and move along to the next command.

I cant find anything, and not sure its even possible. The best I could find was someone making a CRON job to start in a minute.

Cristian
  • 198,401
  • 62
  • 356
  • 264
greg
  • 911
  • 1
  • 7
  • 6
  • 1
    If you have to do this frequently, you might also be interested in a [JobQueue, like Gearman](http://de2.php.net/manual/en/book.gearman.php). – Gordon Sep 29 '10 at 07:15

7 Answers7

147

From the documentation:

In order to execute a command and have it not hang your PHP script while
it runs, the program you run must not output back to PHP. To do this,
redirect both stdout and stderr to /dev/null, then background it.

> /dev/null 2>&1 &

In order to execute a command and have
it spawned off as another process that
is not dependent on the Apache thread
to keep running (will not die if
somebody cancels the page) run this:

exec('bash -c "exec nohup setsid your_command > /dev/null 2>&1 &"');

Emre Erkan
  • 8,433
  • 3
  • 48
  • 53
Cristian
  • 198,401
  • 62
  • 356
  • 264
  • 3
    Thank you so much! There are lots of "solutions" which don't actually work (The main browser thread is still waiting). Many solutions only tell about the "&" at the end which is not sufficient. That said, for me a simpler solution worked to: exec('nohup your_command > /dev/null 2>&1 &') was enough. – Vincent Pazeller Jun 27 '13 at 08:41
  • Why don't you need to also port `stdin` to /dev/null? Will a process' input being linked to a shell be enough to stop `nohup` from "disowning" the child process? (They do change `stdin` in this answer: http://superuser.com/questions/178587/how-do-i-detach-a-process-from-terminal-entirely) – NHDaly Sep 07 '13 at 13:43
  • also, why do you call both `nohup` and `setsid`? I can't find much information about which one is better or how they are different.. (http://stackoverflow.com/questions/10247721/on-writing-a-linux-shell-script-to-safely-detach-programs-from-a-terminal) – NHDaly Sep 07 '13 at 13:52
  • @Christin: Your solution is working for my question: http://stackoverflow.com/questions/25700904/how-to-run-php-code-in-the-background can you put an answer to that question. Then i can close that question with a green answer. – sugunan Sep 06 '14 at 18:04
  • @Christin : Can you please take a look at my issue it seems same as my issue : http://stackoverflow.com/questions/35331958/how-to-execute-script-in-silent-mode-to-get-rid-from-browser-hang-on – Naresh Feb 11 '16 at 06:59
  • Is there a way to do this in Windows? – raphael75 Jan 09 '17 at 13:05
  • Thanks for this answer! Although to be nit-picky, a comment on the English PHP docs isn't quite the same as an official PHP recommendation. – rinogo Aug 02 '17 at 20:39
  • [setsid](https://unix.stackexchange.com/questions/240646/why-we-use-setsid-while-daemonizing-a-process) to ignore dead parent makes [nohup](https://en.wikipedia.org/wiki/Nohup) to ignore dead terminal redundant. – Cees Timmerman Oct 19 '17 at 11:23
  • Super solutions. Thank you so much. – Faisal Jul 19 '19 at 10:48
  • While I agree with the answer in general, it is not necessary (and usually not even a good idea) to pipe stdout and (especially) stderr to /dev/null. Certainly pipe them to somewhere, but preferably this will be a permanent file, making mystery less likely when something doesn't work. – Dennis Feb 25 '22 at 14:45
56

You can run the command in the background by adding a & at the end of it as:

exec('run_baby_run &');

But doing this alone will hang your script because:

If a program is started with exec 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.

So you can redirect the stdout of the command to a file, if you want to see it later or to /dev/null if you want to discard it as:

exec('run_baby_run > /dev/null &');
codaddict
  • 445,704
  • 82
  • 492
  • 529
10

This uses wget to notify a URL of something without waiting.

$command = 'wget -qO- http://test.com/data=data';
exec('nohup ' . $command . ' >> /dev/null 2>&1 & echo $!', $pid);

This uses ls to update a log without waiting.

$command = 'ls -la > content.log';
exec('nohup ' . $command . ' >> /dev/null 2>&1 & echo $!', $pid);
Leandro Bardelli
  • 10,561
  • 15
  • 79
  • 116
Paul T
  • 396
  • 3
  • 7
7

I know this question has been answered but the answers i found here didn't work for my scenario ( or for Windows ).

I am using windows 10 laptop with PHP 7.2 in Xampp v3.2.4.

$command = 'php Cron.php send_email "'. $id .'"';
if ( substr(php_uname(), 0, 7) == "Windows" )
{
    //windows
    pclose(popen("start /B " . $command . " 1> temp/update_log 2>&1 &", "r"));
}
else
{
    //linux
    shell_exec( $command . " > /dev/null 2>&1 &" );
}

This worked perfectly for me.

I hope it will help someone with windows. Cheers.

Anil Prz
  • 1,099
  • 10
  • 14
  • Thank you, just what I needed. – DrLightman Mar 29 '21 at 21:51
  • The system cannot find the path specified. I think temp/update_log this is not clear.can you explain? – rahul singh May 01 '21 at 19:07
  • @rahulsingh That file path is just the file from your current working directory, meaing, it assumes you have a folder name `temp` in your current directory with a file inside that folder called `upload_log`, that's it. – Anil Prz May 07 '21 at 02:13
  • 1
    A slight variant of this works for me on Windows. Instead of: `pclose(popen("start /B " . $command . " 1> temp/update_log 2>&1 &", "r"));` I used: `pclose(popen("start /B " . $command . " 1> NUL 2>&1 &", "r"));` And it works. – Nikhil Sinha Jun 07 '22 at 13:58
2

There are two possible ways to implement it. The easiest way is direct result to dev/null

exec("run_baby_run > /dev/null 2>&1 &");

But in case you have any other operations to be performed you may consider ignore_user_abort In this case the script will be running even after you close connection.

1

"exec nohup setsid your_command"

the nohup allows your_command to continue even though the process that launched may terminate first. If it does, the the SIGNUP signal will be sent to your_command causing it to terminate (unless it catches that signal and ignores it).

jobeard
  • 99
  • 2
  • 3
  • According to [this answer](https://stackoverflow.com/a/284443/819417), a child has to sign up for SIGHUP to be notified of its parent's death. A terminal tends to send the HUP signal on exit, though. – Cees Timmerman Oct 19 '17 at 12:12
0

On Windows, you may use the COM object:

if(class_exists('COM')) {
    $shell = new COM('WScript.Shell');
    $shell->Run($cmd, 1, false);
}
else {
    exec('nohup ' . $cmd . ' 2>&1 &');
}
Benjamin
  • 81
  • 7