programing

PHP에서 STDOUT을 파일로 리디렉션하는 방법은 무엇입니까?

projobs 2021. 1. 17. 10:23
반응형

PHP에서 STDOUT을 파일로 리디렉션하는 방법은 무엇입니까?


아래 코드는 거의 작동하지만 실제로 의미하는 것은 아닙니다.

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

더 자연스러운 방법이 있습니까?


출력 버퍼링을 사용하는 것보다 훨씬 쉽고 간단하게 PHP의 파일에 STDOUT을 직접 작성할 수 있습니다.

스크립트의 맨 처음에 다음을 수행하십시오.

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를 더 큰 값으로 변경할 수 있습니다.

이제 로그 파일을 꼬리 -f하십시오.

tail -f log.txt

eio pecl 모듈을 사용하는 것은 매우 쉽습니다. 또한 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 호출에서 'wb'대신 'ab'모드를 사용하십시오.

Install eio module is very easy (http://php.net/manual/es/eio.installation.php). I tested this example with version 1.2.6 of eio module.


Here is an ugly solution that was useful for a problem I had (need to debug).

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

The main drawback of that is that you'd better not to use the $_POST variables. But you dont have to put it in the very beggining.


You can install Eio extension

pecl install eio

and duplicate a file descriptor

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

this creates new file descriptor and rewrites target stream of STDOUT

this can be done with STDERR as well

and constants STD[OUT|ERR] are still usable

ReferenceURL : https://stackoverflow.com/questions/937627/how-to-redirect-stdout-to-a-file-in-php

반응형