Skip to content

Instantly share code, notes, and snippets.

@sandermarechal
Created March 5, 2012 11:12
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save sandermarechal/1977896 to your computer and use it in GitHub Desktop.
Save sandermarechal/1977896 to your computer and use it in GitHub Desktop.
PHP problem using passthru() on bash script that uses process replacement

This gist shows a problem I have with PHP's passthru() and exec() functions.

I have a shell script called daemon that starts a background daemon. I'm my real project the background daemon is a Node.js server. Here I replaced it with a dummy daemon.php script. The shell script acts as a wrapper to make it easy to start and stop the server.

I also have a build script (Phing, here represented by a dummy phing.php script). Phing can start the server using the shell script as well. But only if the shell script does not use process replacement. If the shell script does that, the passthru() call to the shell script will block. If the shell script just uses a regular path to a logfile, everything works as expected.

#!/bin/bash
# Start daemon, using a syslog file descriptor as logfile
# This causes the phing.php passthru() to hang
./daemon.php >(logger -t daemon.php)
# This will work fine from phing.php
# ./daemon.php out.log
#!/usr/bin/php
<?php
/**
* This is just a dummy daemon. My other daemon is Node.js :-)
* The point is that this daemon doesn't log to syslog itself.
* It just writes to file descriptors (like Node.js does)
*/
echo "Starting daemon\n";
// Fork to the background
if (pcntl_fork() !== 0) {
exit(0);
}
// Close file descriptors
fclose(STDIN);
fclose(STDOUT);
fclose(STDERR);
// Open logfile
$path = $_SERVER['argv'][1];
if (preg_match('#/dev/fd/\d+#', $path)) {
// Open file descriptor
$fd = strrchr($_SERVER['argv'][1], '/');
$logfile = fopen('php://fd' . $fd, 'a');
} else {
// Open regular logfile
$logfile = fopen($path, 'a');
}
// Loop-da-loop!
while (true) {
fwrite($logfile, "Daemon running\n");
sleep(1);
}
#!/usr/bin/php
<?php
/**
* This would be my PHP build script (for example, Phing)
* One of its responsibilities is starting a background server
*/
// If `daemon` uses process redirection, this call blocks
// If `daemon` just uses a regular log file, this starts the daemon and then returns
passthru('./daemon');
// Same problem with exec()
exec('./daemon');
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment