5

Unfortunately, I've found all the solutions for executing external programs not suitable, so I use my own implementation, which is pcntl_exec after pcntl_fork.

But now I need to redirect stderr/stdout of the executed program into some file. It's obvious, that I should use some sort of dup2 Linux call after pcntl_fork, but the only dup2 I can see in PHP is eio_dup2, which looks like it operates not the regular streams (like stderr/stdout), but some async streams.

How can I call dup2 from PHP or how can I redirect std* without it?

The same question (though, without details) has no answers: How do I invoke a dup2() syscall from PHP ?

Community
  • 1
  • 1
Dmitry Ginzburg
  • 7,391
  • 2
  • 37
  • 48

1 Answers1

4

Here comes a way without the need of dup2. It is based on this answer.

$pid = pcntl_fork();

switch($pid) {

    case 0:
        // Standard streams (stdin, stdout, stderr) are inherited from
        // parent to child process. We need to close and re-open stdout 
        // before calling pcntl_exec()

        // Close STDOUT
        fclose(STDOUT);

        // Open a new file descriptor. It will be stdout since 
        // stdout has been closed before and 1 is the lowest free
        // file descriptor
        $new_stdout = fopen("test.out", "w");

        // Now exec the child. It's output goes to test.out
        pcntl_exec('/bin/ls');

        // If `pcntl_exec()` succeeds we should not enter this line. However,
        // since we have omitted error checking (see below) it is a good idea
        // to keep the break statement
        break; 

    case -1: 
        echo "error:fork()\n";
        exit(1);

    default:
        echo "Started child $pid\n";
}

Error handling has been omitted for brevity. But keep in mind that in system programming should carefully handle any function return value.

Community
  • 1
  • 1
hek2mgl
  • 152,036
  • 28
  • 249
  • 266