Categories
josephscott

Fake Fork in PHP

If you aren’t using the Apache module then using pcntl_fork() to fork a PHP process works fine. There are times when it would be really handy to perform a fork in PHP when it is running as an Apache module. There is a way to fake this, sort of.

Instead of forking your PHP script you can exec() another process to run in the background. This obviously isn’t the same as forking, but it is about as close as you can get when running as an Apache module. While reading through the comments on the PHP exec() page I was able to piece together enough information to make execing a background process work. Here’s an example:

exec("/usr/local/bin/myprog 2>/dev/null >&- /dev/null &");

This will execute /usr/local/bin/myprog and redirect STDOUT and STDERR to /dev/null and run the process in the background. You can even pass arguments to your program like this:

$safe_arg["arg_1"] = escapeshellarg($arg_1);
$safe_arg["arg_2"] = escapeshellarg($arg_2);
exec("/usr/local/bin/myprog {$safe_arg["arg_1"]} {$safe_arg["arg_2"]} 2>/dev/null >&- /dev/null &");

Make sure that you escape any data you get from outside your script when using it in exec().

9 replies on “Fake Fork in PHP”

Thanks so much for this! I needed to create a background process and tried pcntl_fork, but couldn’t do it because I’m using Apache. So I was stuck, until I luckily hit this web page. That’s really great Unix work nutting out that command line! I fiddled with it a bit, and worked out 1. You do seem to need all those options – “&” is not enough, and 2. in ‘< &- ‘ the space is not necessary, ‘<&- ‘ works fine.

Thanks again!

Sorry, but this isn’t a fork fake or similar such thing. The system call fork(2) — wrapped arround php with pcntl_fork() function — sets the entry point to the right line of source, instead your implementation that set the entry point to the start of the script.

Play a little with labels if you want the desired results. Also, see the way to save the environment and allocated variables… Be careful y you serialize the $GLOBALS variable.

Another way to perform several tasks simultaneously is by using stream_select(). This is useful in the cases where you php script makes many requests to multiple other websites.

In one of my web scripts, I had to make up to 24 http requests. When I done it sequentially, it took over 1 minute. Now it takes less than 10 seconds. See it and test it here: http://www.info-express.org/website-popularity-checker

[…] Of course in the LAMP development world a quick and dirty hack is often as good as a well rounded programmewd solution. Joseph Scott shows you how to use a Linux execution feature (namely forking a command into the background using and ampersand) to parallelise applications that don’t need to return anything. I’ve actually used this technique to build a one hit multiplexor for various applications: Quick and dirty fake fork for non returning scripts […]

Cheers mate. I was looking for this for thttpd+php on an AT91SAM board for launching mpg123.
Works a treat!

How can you call sequential commands to run in the background? In my case, I want to call one command which waits for a specific event; once this finished I want the next command to be called. Both of these need to happen in the same “background process”, but sequentially. The only way I can think of realizing this would be to call another script:
exec(“php otherScript.php > /dev/null”, $array_output);

However, I prefer not doing this.

Leave a Reply

Your email address will not be published. Required fields are marked *