Как перенаправить STDOUT в файл в PHP? - PullRequest
52 голосов
/ 02 июня 2009

Код ниже почти работает, но я не это имел в виду:

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

Есть ли более естественный способ?

Ответы [ 7 ]

118 голосов
/ 29 сентября 2010

Возможно записать 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 не будет обновлять эти константы до новых дескрипторов, и ему не разрешается переопределять эти константы (в конце концов, они называются константами по причине).

16 голосов
/ 07 ноября 2012

вот способ отвлечь 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

9 голосов
/ 02 июня 2009

Нет, выходная буферизация хороша. Хотя немного приятнее просто сделать

ob_start();
echo 'xxx';
$contents = ob_get_flush();
file_put_contents($file,$contents);
2 голосов
/ 24 февраля 2017

Ни один из ответов не сработал для моего конкретного случая, когда мне нужен был кроссплатформенный способ перенаправления вывода, как только он выводился эхом, чтобы я мог следить за журналами с помощью 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
1 голос
/ 01 июня 2016

Использование модуля 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.

1 голос
/ 09 сентября 2015

Вы можете установить расширение 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] все еще могут использоваться

1 голос
/ 25 ноября 2012

Вот уродливое решение, которое было полезно для моей проблемы (нужно отладить).

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. Но вы не должны ставить это в самом начале.

...