4

I am calling some bash code from php, but even though I fork the bash (with &), the php will not finish before the full bash is done.

This code:

<html>
<body>
HTML START<br>
<pre>
<?php
echo "PHP START\n";
echo `sleep 30 &`;
echo "PHP END\n";
?>
</pre>
HTML END<br>
</body>
</html>

Will not show anything in the browser, before after 30 seconds.

What I really want is to start a GUI app from php, that should continue to run.

hpekristiansen
  • 1,030
  • 3
  • 17
  • 35
  • Here is the answer: http://stackoverflow.com/questions/222414/asynchronous-shell-exec-in-php – Toto May 16 '12 at 16:26
  • @Toto I'm actually not sure I like that answer -- re-opening a file descriptor to `/dev/null` is ever so slightly more inefficient than just closing it. – Charles Duffy May 16 '12 at 16:28
  • @CharlesDuffy, yes, but keeping fds 0, 1 and 2 open to something harmless avoids problems with naive code that you can't necessarily avoid. Some code just can't imagine life without STDIN/OUT/ERR. Worse, fds allocated thereafter (as by an innocent pipe()) will arrive as 0, 1 and 2, which makes for a *nasty* surprise when some hidden routine you didn't write complains with `fprintf(stderr, "bummer\n")`. – pilcrow May 16 '12 at 16:40

5 Answers5

3

Close all file descriptors in your sleep call to allow it to detach:

<?php
echo "PHP START\n";
echo `sleep 30 <&- 1<&- 2<&- &`;
echo "PHP END\n";
?>

Otherwise, the output file descriptor is still open, and PHP is still trying to wait to receive its output, even with the process no longer attached directly.

This works correctly when run, immediately exiting but leaving a sleep process behind:

$ time php5 test.php; ps auxw | grep sleep | grep -v grep
PHP START
PHP END

real    0m0.019s
user    0m0.008s
sys         0m0.004s
cduffy    6239  0.0  0.0  11240   576 pts/0    S    11:23   0:00 sleep 30
Charles Duffy
  • 280,126
  • 43
  • 390
  • 441
1

PHP waits for the called process to terminate even if the amperstand is explicit given

rollstuhlfahrer
  • 3,988
  • 9
  • 25
  • 38
  • 1
    Not true -- it isn't waiting on the process to terminate (as with a `wait()` syscall), it's waiting on the _output_ of the process to terminate (the output file handle to be closed). – Charles Duffy May 16 '12 at 16:20
0

Maybe create another HTTP process by using an Ajax call to another PHP script, which task will be to launch asynchronously your sleep 30 command, or whatever you want, on the server.

Maxime Pacary
  • 22,336
  • 11
  • 85
  • 113
0

what you probably want to do is seperate the forked processes. One way to do this is using nohup in the bash command.

for examples look at the user comments on php.net > exec, especially this one: http://www.php.net/manual/en/function.exec.php#88704

be carefull, though, you lose direct feedback and have to monitor your processes/results through other means

cypherabe
  • 2,562
  • 1
  • 20
  • 35
-1
sleep(30);

mast be...

<?php
echo "PHP START\n";
echo sleep(30);
echo "PHP END\n";
?>
johniek_comp
  • 322
  • 3
  • 8
  • I'm reading this such that sleep is a stand-in for a different, long-running process which the questioner intends to run in the background. – Charles Duffy May 16 '12 at 16:19
  • Note that the OP uses backticks. This is entierely valid for executing system commands from PHP. See: http://www.php.net/manual/en/language.operators.execution.php – Maxime Pacary May 16 '12 at 16:20
  • sleep is bash!! - just an example, of something, that I want to run. – hpekristiansen May 16 '12 at 16:21