Код ниже почти работает, но это не то, что я действительно имел в виду:
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);
Вот уродливое решение, которое было полезно для проблемы, которую я имел (нужно отлаживать).
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 install 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] все еще пригодны для использования
Использование eio pecl module 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.
Ни один из ответов не работал для моего конкретного случая, когда мне нужен был кросс-платформенный способ перенаправления вывода, как только он был эхо-кодом, чтобы я мог следить за журналами с помощью 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