如何将STDOUT重定向到PHP中的文件?

时间:2009-06-02 01:53:07

标签: php stdout stdin

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

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

有更自然的方式吗?

6 个答案:

答案 0 :(得分:118)

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

在脚本的最开头执行此操作:

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

为什么一开始你可能会问?不应该打开文件描述符,因为当您关闭标准输入,输出和错误文件描述符时,前三个新描述符将成为新的标准输入,输出和错误文件描述符。

在我的示例中,我将标准输入重定向到/ dev / null,将输出和错误文件描述符重定向到日志文件。在PHP中创建守护程序脚本时,这是常见的做法。

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

echo "Hello world\n";

要写入 error.log ,必须执行以下操作:

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

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

答案 1 :(得分:16)

这是一种转移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

答案 2 :(得分:9)

不,输出缓冲是最好的。虽然它只是做得好一点

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

答案 3 :(得分:2)

没有一个答案适用于我的特殊情况,我需要一个跨平台的方式,一旦它被回显,就重定向输出,以便我可以使用tail -f log.txt或其他日志查看来跟踪日志应用程序。 我提出了以下解决方案:

$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更改为更大的值。

现在只需尾随日志文件:

tail -f log.txt

答案 4 :(得分:1)

这是一个丑陋的解决方案,对我遇到的问题(需要调试)非常有用。

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);
}

主要缺点是你最好不要使用$ _POST变量。 但你不必把它放在开始的时候。

答案 5 :(得分:1)

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

$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版测试了这个例子。

相关问题