programing

STDOUT을 PHP의 파일로 리디렉션하는 방법?

stoneblock 2023. 9. 11. 21:24

STDOUT을 PHP의 파일로 리디렉션하는 방법?

아래의 코드는 거의 작동하지만, 제가 의도한 바는 아닙니다.

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는 이러한 상수를 새 디스크립터로 업데이트하지 않으며 이러한 상수를 재정의하는 것이 허용되지 않습니다(결국 이유로 상수라고 함).

원래 문제인 것처럼 보이는 출력을 다른 방향으로 돌리는 방법이 있습니다.

$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

출력이 에코 아웃되자마자 출력을 재연결하여 로그를 추적할 수 있는 교차 플랫폼 방식이 필요한 경우에는 어떤 대답도 통하지 않았습니다.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

아니요, 출력 버퍼링은 아주 좋습니다.그냥 하는 게 좀 낫긴 하지만,

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

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 요청이 처리되었는지 확인하는 데 사용됩니다.로그 온, 오프 콜 시 추가가 필요한 경우 wb 대신 ab 모드를 사용합니다.

설치 eio 모듈은 매우 쉽습니다(http://php.net/manual/es/eio.installation.php) .eio module 1.2.6 버전으로 이 예제를 테스트했습니다.

Eio extension을 설치할 수 있습니다.

페클 인스톨리오

파일 설명자를 복제합니다.

$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]은(는) 여전히 사용 가능합니다.

이 질문이 오래된 질문이라는 것을 이해하지만, 이 질문을 하려는 사람들은 결국 여기서 끝나게 될 것입니다.당신 둘 다.

특정 환경에서 실행 중인 경우...

  • Linux에서 실행(아마도 대부분의 다른 유닉스는 운영 체제와 비슷하지만 테스트되지 않음)
  • CLI를 통해 실행(웹 서버에서 테스트되지 않음)

실제로 모든 파일 설명자를 닫을 수 있습니다(그렇습니다. 즉, 실행을 시작할 때 이 작업을 수행하는 것이 최선일 것입니다.)예를 들어 A 직후에pcntl_fork()프로세스를 데몬에서 백그라운드로 호출합니다(이와 같은 것에 대한 가장 일반적인 요구처럼 보임).

fclose( STDIN );  // fd 3
fclose( STDERR);  // fd 2
fclose( STDOUT ); // fd 1

그런 다음 파일 설명자를 다시 열어 범위를 벗어나지 않으므로 가비지를 수집할 수 있는 변수에 할당합니다.왜냐하면 리눅스는 그것들을 적절한 순서로 예측 가능하게 열 것이기 때문입니다.

$kept_in_scope_variable_fd1 = fopen(...); // fd 1
$kept_in_scope_variable_fd2 = fopen(...); // fd 2
$kept_in_scope_variable_fd3 = fopen( '/dev/null', ... ); // fd 3

원하는 파일이나 장치를 사용할 수 있습니다.STDIN(fd3)의 예로 /dev/null을 든 것은 아마도 이런 종류의 코드가 가장 일반적인 경우일 것이기 때문입니다.

되면 이 과 인 을 할 되면 할 을 이 인 되면 echo,print_r,var_dump쓸 없이, 에 이 .이것은 파일 포인터 출력에 적합하도록 다시 쓰기를 원하지 않거나 할 수 없는 코드를 배경화하려고 할 때 유용합니다.

다른 환경 및 기타 FD 개방 등을 위한 YMMV.간단한 테스트 스크립트로 시작하여 환경에서 작동하는지 여부를 입증한 다음 통합 단계로 넘어가라는 조언을 드립니다.

행운을 빌어요.

여기 제가 가진 문제(디버그가 필요한)에 유용했던 추한 해결책이 있습니다.

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 변수를 사용하지 않는 것이 좋다는 것입니다.하지만 그것을 맨 처음에 넣을 필요는 없습니다.

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