PHP Stderr After Exec()

Capture/supress all output from php exec including stderr

Command proc_exec() allows to deal with file descriptors of the exec-ed command, using pipes.

The function is: proc_open ( string $cmd , array $descriptorspec , array &$pipes […optional parameters] ) : resource

You give you command in $cmd (as in exec) and you give an array describing the filedescriptors to "install" for the command. This array is indexed by filedescriptor number (0=stdin, 1=stdout…) and contains the type (file, pipe) and the mode (r/w…) plus the filename for file type.

You then get in $pipes an array of filedescriptors, which can be used to read or write (depending of what requested).

You should not forget to close these descriptors after usage.

Please refer to PHP manual page (and in particular the examples): https://php.net/manual/en/function.proc-open.php

Note that read/write is related to the spawned command, not the PHP script.

How can I redirect the output of a exec call in php ( and its stderr) to the calling program?

PHP's exec() is quite unlike the exec() of any other language.

When invoked as just exec("some string"), it gets some string interpreted as shell code by a shell in a child process, and returns the last line of its output stripped of all the trailing ASCII whitespace characters.

Here, you're not doing anything with that output though.

Now as to that:

/usr/bin/php -f t.php 2 2&>1

shell code, note that the behaviour varies between sh implementations.

In POSIX compliant sh implementations, that's meant to be the same as:

/usr/bin/php -f t.php 2 2 &
>1

That is run that php command in background, and then open the file called 1 for writing, but without any command whose output to send there.

Not all sh implementations are compliant there are some shells implement a non-standard &> redirection operator.

In the GNU implementation of sh (bash), that's interpreted as:

/bin/bin/php -f t.php 2 2 &> "1"

Which is running that php command (with 2 "2" arguments) with both stdout and stderr redirected to the file called 1. So it will produce no output on stdout (captured by php) but send /usr/bin/php's output to that file.

In zsh, the 2&> "1" redirects both fd 2 and fd 2 to the file called 1, as if you had written 2> "1" 2>&2. With fd 2 redirected twice, zsh normally implements a tee-like behaviour where the data is sent to both locations (here the same), but when invoked as sh (not that many systems have sh implemented with zsh), zsh disables that tee-like feature, so the 2&>1 ends up being the same as 2> "1", so redirects stderr to the file called 1. In any case, since that php command doesn't output anything on stderr, it makes no difference.

mksh (MirBSD sh) behaves like zsh-as-sh above.

Here, you could do

echo exec('/usr/bin/php -f t.php') . "\n";

To print the contents of the last line of the output of that php command followed by a newline character. Or (maybe what you intended?):

echo exec('/usr/bin/php -f t.php 2>&1') . "\n";

For the last line of the output+errors of that php command.

But here, it sounds like you just want to leave the output of that php command untouched; not capture it, but let it go to the same destination as the echo does.

PHP has some system() and passthru() functions, but those capture the output of the shell command to display it afterwards.

You can however use the pcntl_exec() function which is more like the exec() of other languages, except that it doesn't let you set argv[0].

pcntl_exec("/usr/bin/php", ["-f", "t.php", "2"]);

Like the exec() of other languages, it runs it in the same process, so it's the last thing the php script will do. And it doesn't invoke a shell, just runs the command directly.

That's probably not what you'll want to use in a web application though. In a web application, php needs to know what output it's going to send before it sends it, if only to fill in Content-Length type of HTTP header. There, you'd use passthru() or system() or shell_exec()...

See also:

  • shell_exec()
  • passthru()
  • system()
  • proc_open()
  • popen()

exec() error responses

You should redirect stderr to stdout somehow like this

$stout = exec($command . " 2>&1", $output, $status);

See also here
PHP StdErr after Exec()



Related Topics



Leave a reply



Submit