如何将STDOUTredirect到PHP中的文件?

下面的代码几乎可以工作,但这不是我真正的意思:

ob_start(); echo 'xxx'; $contents = ob_get_contents(); ob_end_clean(); file_put_contents($file,$contents); 

有没有更自然的方式?

可以直接将STDOUT写入PHP中的文件,这比使用输出缓冲更容易,更直接。

在脚本的一开始就这样做:

 fclose(STDIN); fclose(STDOUT); fclose(STDERR); $STDIN = fopen('/dev/null', 'r'); $STDOUT = fopen('application.log', 'wb'); $STDERR = fopen('error.log', 'wb'); 

为什么在一开始你可能会问? 没有文件描述符应该被打开,因为当你closures标准input,输出和错误文件描述符时,前三个新的描述符将成为新的标准input,输出和错误文件描述符。

在我的例子中,我将标准inputredirect到/ dev / null,将输出和错误文件描述符redirect到日志文件。 在PHP中创build守护进程脚本时,这是很常见的做法。

要写入application.log文件,这就足够了:

 echo "Hello world\n"; 

要写入error.log ,你必须这样做:

 fwrite($STDERR, "Something went wrong\n"); 

请注意,当你改变input,输出和错误描述符时,内build的PHP常量STDIN,STDOUT和STDERR将不可用。 PHP不会将这些常量更新为新的描述符,并且不允许重新定义这些常量(毕竟,它们被称为常量)。

这是一个转移OUTPUT的方式,这似乎是原来的问题

 $ob_file = fopen('test.txt','w'); function ob_file_callback($buffer) { global $ob_file; fwrite($ob_file,$buffer); } ob_start('ob_file_callback'); 

更多信息在这里:

http://my.opera.com/zomg/blog/2007/10/03/how-to-easily-redirect-php-output-to-a-file

不,输出缓冲是一样好。 虽然稍微好一些

 ob_start(); echo 'xxx'; $contents = ob_get_flush(); file_put_contents($file,$contents); 

这是一个丑陋的解决scheme,对于我有问题(需要debugging)是有用的。

 if(file_get_contents("out.txt") != "in progress") { file_put_contents("out.txt","in progress"); $content = file_get_contents('http://'.$_SERVER['HTTP_HOST'].$_SERVER['REQUEST_URI']); file_put_contents("out.txt",$content); } 

这样做的主要缺点是你最好不要使用$ _POSTvariables。 但是你不必把它放在开始的时候。

您可以安装Eio扩展

pecl安装eio

并复制一个文件描述符

 $temp=fopen('/tmp/my_stdout','a'); $my_data='my something'; $foo=eio_dup2($temp,STDOUT,EIO_PRI_MAX,function($data,$esult,$request){ var_dump($data,$esult,$request); var_dump(eio_get_last_error($request)); },$my_data); eio_event_loop(); echo "something to stdout\n"; fclose($temp); 

这将创build新的文件描述符并重写STDOUT的目标stream

这也可以用STDERR来完成

和常数STD [OUT | ERR]仍然可用

使用eio pecl模块eio非常简单,你也可以捕获PHP内部错误,var_dump,echo等。在这段代码中,你可以find一些不同情况的例子。

 $fdout = fopen('/tmp/stdout.log', 'wb'); $fderr = fopen('/tmp/stderr.log', 'wb'); eio_dup2($fdout, STDOUT); eio_dup2($fderr, STDERR); eio_event_loop(); fclose($fdout); fclose($fderr); // output examples echo "message to stdout\n"; $v2dump = array(10, "graphinux"); var_dump($v2dump); // php internal error/warning $div0 = 10/0; // user errors messages fwrite(STDERR, "user controlled error\n"); 

调用eio_event_loop用于确保以前的eio请求已经被处理。 如果你需要附加日志,在fopen调用,使用模式'ab'而不是'wb'。

安装eio模块非常简单( http://php.net/manual/es/eio.installation.php )。 我用eio模块的1.2.6版本testing了这个例子。

没有一个答案适用于我的特殊情况,我需要一个跨平台的方式redirect输出一旦它被echo'd out,以便我可以跟踪日志尾-f log.txt或另一个日志查看应用程序。 我想出了以下解决scheme:

 $logFp = fopen('log.txt', 'w'); ob_start(function($buffer) use($logFp){ fwrite($logFp, $buffer); }, 1); //notice the use of chunk_size == 1 echo "first output\n"; sleep(10) echo "second output\n"; ob_end_clean(); 

我没有注意到任何性能问题,但如果你这样做,你可以改变chunk_size为更大的值。

现在只是尾巴-f日志文件:

 tail -f log.txt