下面的代码几乎可以工作,但这不是我真正的意思:
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');
为什么一开始你可能会问?还不应打开任何文件描述符,因为当您关闭标准输入、输出和错误文件描述符时,前三个新的描述符将成为新的标准输入、输出和错误文件描述符。
在我的示例中,我将标准输入重定向到 /dev/null 并将输出和错误文件描述符重定向到日志文件。这是在 PHP 中制作守护程序脚本时的常见做法。
要写入application.log文件,这就足够了:
echo "Hello world\n";
要写入error.log,必须这样做:
fwrite($STDERR, "Something went wrong\n");
请注意,当您更改输入、输出和错误描述符时,内置 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);
没有一个答案适用于我的特殊情况,我需要一种跨平台的方式来在输出回显后立即重定向输出,以便我可以使用 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 日志文件:
tail -f log.txt
使用 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)。我用 1.2.6 版的 eio 模块测试了这个例子。
这是一个丑陋的解决方案,对我遇到的问题(需要调试)很有用。
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 变量。但你不必把它放在最开始。
您可以安装 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);
这会创建新的文件描述符并重写 STDOUT 的目标流
这也可以用 STDERR 完成
和常量 STD[OUT|ERR] 仍然可用