为什么我不能写到/ dev / stdout,但是php:// stdout可以工作?

时间:2019-06-13 15:07:50

标签: php linux apache docker

我正在尝试使用PHP和Apache(在Docker中在前台运行)写到stdout(或stderr)。

这些作品:

file_put_contents( "php://stderr","works" );
file_put_contents( "php://stdout","works" );

$fh = fopen('php://stdout','w'); fwrite($fh, "works");

但是这些不是:

$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确实存在,但是不可写。并且fopen('/dev/stdout')返回FALSE。

fd1 exists:yes
fd1 writable:no
stdout exists:yes
stdout writable:no

更多信息:

  • 我尝试在php.ini中设置error_log = /dev/stdout,但不起作用
  • 我尝试了Docker命令RUN ln -sf /dev/stdout stdout.log,然后用PHP写入stdout.log,但没有。

再次,php:// stdout在做什么,我不这样做?

1 个答案:

答案 0 :(得分:1)

原因是Apache派生用户并将其更改为特权较低的用户(“ apache”用户),该用户无权编写/dev/stdout。解决这个问题没有简单的方法,所以我最后写了一个脚本。

该脚本创建一个文件(管道),该文件通过“ cat”进程连接,该进程写入标准错误(作为根用户):

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

现在您可以在php.ini中设置error_log = logpipe,所有php错误都将发送到stderr。

至于php://stdout为何起作用,我猜想PHP使用的是Apache /dev/stdout已打开的文件。

更多详细信息here