Reputation: 19925
I'm trying to write to stdout (or stderr) using PHP with Apache (running in the foreground in Docker).
These works:
file_put_contents( "php://stderr","works" );
file_put_contents( "php://stdout","works" );
$fh = fopen('php://stdout','w'); fwrite($fh, "works");
But these do not:
$stdout = fopen ("/dev/stdout","w"); fwrite($stdout, "fails");
$stderr = fopen ("/dev/stderr","w"); fwrite($stderr, "fails");
echo "fd1 exists:" . (file_exists('/proc/self/fd/1') ? 'yes' : 'no');
echo "fd1 writable:" . (is_writable('/proc/self/fd/1') ? 'yes' : 'no');
echo "stdout exists:" . (file_exists('/dev/stdout') ? 'yes' : 'no');
echo "stdout writable:" . (is_writable('/dev/stdout') ? 'yes' : 'no');
file_put_contents( "/proc/self/fd/1", "fails" );
file_put_contents( "/proc/self/fd/2", "fails" );
file_put_contents( "/dev/stdout", "fails" );
fwrite(STDOUT, 'fails');
fwrite(STDERR, 'fails');
/dev/stdout do exist, but is not writable. also fopen('/dev/stdout')
returns FALSE.
fd1 exists:yes
fd1 writable:no
stdout exists:yes
stdout writable:no
More info:
error_log = /dev/stdout
in php.ini, but it doesn't work RUN ln -sf /dev/stdout stdout.log
and then writing to stdout.log
in PHP, but nope.Again, what is php://stdout doing that I don't?
Upvotes: 3
Views: 3974
Reputation: 19925
The reason is that Apache forks and changes user to a less privileged one (the "apache" user) which does not have permission to write /dev/stdout
. There is no easy way around this, so I ended up with a script.
The script creates a file (pipe) which is connected through a 'cat' process which writes to standard error (as root):
mkfifo -m 600 logpipe
chown apache:apache logpipe
cat <> logpipe 1>&2 &
CAT=$!
# Start apache
/usr/sbin/httpd -D FOREGROUND
# Kill the cat after apache dies
kill $CAT
Now you can set error_log = logpipe
in php.ini and all php errors will be sent to stderr.
As for why php://stdout
works, my guess is that PHP uses a file handle (to /dev/stdout
) which is already opened by Apache.
More details here.
Upvotes: 2