복붙노트

PHP로 실시간 출력으로 프로세스 실행

PHP

PHP로 실시간 출력으로 프로세스 실행

실시간으로 출력을 반환하는 웹 페이지에서 프로세스를 실행하려고합니다. 예를 들어, 'ping'프로세스를 실행하면 새로운 행을 반환 할 때마다 내 페이지를 업데이트해야합니다. (지금은 exec (command, output)을 사용할 때 -c 옵션을 사용해야하고 프로세스가 끝날 때까지 기다려야합니다. 내 웹 페이지에 출력). php에서 이것을 할 수 있습니까?

나는 누군가가 페이지를 떠날 때 이런 종류의 과정을 죽이는 올바른 방법이 무엇인지 궁금하다. 'ping'프로세스의 경우 시스템 모니터에서 실행중인 프로세스를 볼 수 있습니다 (의미가 있습니다).

해결법

  1. ==============================

    1.이것은 나를 위해 일했다 :

    이것은 나를 위해 일했다 :

    $cmd = "ping 127.0.0.1";
    
    $descriptorspec = array(
       0 => array("pipe", "r"),   // stdin is a pipe that the child will read from
       1 => array("pipe", "w"),   // stdout is a pipe that the child will write to
       2 => array("pipe", "w")    // stderr is a pipe that the child will write to
    );
    flush();
    $process = proc_open($cmd, $descriptorspec, $pipes, realpath('./'), array());
    echo "<pre>";
    if (is_resource($process)) {
        while ($s = fgets($pipes[1])) {
            print $s;
            flush();
        }
    }
    echo "</pre>";
    
  2. ==============================

    2.이것은 셸 명령의 실시간 출력을 표시하는 좋은 방법입니다.

    이것은 셸 명령의 실시간 출력을 표시하는 좋은 방법입니다.

    <?php
    header("Content-type: text/plain");
    
    // tell php to automatically flush after every output
    // including lines of output produced by shell commands
    disable_ob();
    
    $command = 'rsync -avz /your/directory1 /your/directory2';
    system($command);
    

    출력 버퍼링을 방지하려면이 기능이 필요합니다.

    function disable_ob() {
        // Turn off output buffering
        ini_set('output_buffering', 'off');
        // Turn off PHP output compression
        ini_set('zlib.output_compression', false);
        // Implicitly flush the buffer(s)
        ini_set('implicit_flush', true);
        ob_implicit_flush(true);
        // Clear, and turn off output buffering
        while (ob_get_level() > 0) {
            // Get the curent level
            $level = ob_get_level();
            // End the buffering
            ob_end_clean();
            // If the current level has not changed, abort
            if (ob_get_level() == $level) break;
        }
        // Disable apache output buffering/compression
        if (function_exists('apache_setenv')) {
            apache_setenv('no-gzip', '1');
            apache_setenv('dont-vary', '1');
        }
    }
    

    그것은 모든 서버에서 작동하지 않습니다,하지만 나는 당신의 PHP 구성에서 작동하도록이 유형의 동작을 얻으려고 밖으로 머리를 당겨 야지 여부를 결정하기 위해 무엇을 찾아야할지에 대한 조언을 제공 할 수 있었으면 좋겠습니다. 귀하의 서버에! 다른 사람 아시 겠죠?

    다음은 일반 PHP의 더미 예제입니다.

    <?php
    header("Content-type: text/plain");
    
    disable_ob();
    
    for($i=0;$i<10;$i++) 
    {
        echo $i . "\n";
        usleep(300000);
    }
    

    나는 이것이 그들의 길을 봤던 다른 사람들을 돕기를 바랍니다.

  3. ==============================

    3.이것을 시험해보십시오 (Windows 컴퓨터 + Wamp 서버에서 테스트 됨).

    이것을 시험해보십시오 (Windows 컴퓨터 + Wamp 서버에서 테스트 됨).

            header('Content-Encoding: none;');
    
            set_time_limit(0);
    
            $handle = popen("<<< Your Shell Command >>>", "r");
    
            if (ob_get_level() == 0) 
                ob_start();
    
            while(!feof($handle)) {
    
                $buffer = fgets($handle);
                $buffer = trim(htmlspecialchars($buffer));
    
                echo $buffer . "<br />";
                echo str_pad('', 4096);    
    
                ob_flush();
                flush();
                sleep(1);
            }
    
            pclose($handle);
            ob_end_flush();
    
  4. ==============================

    4.최신 HTML5 Server Side Events를 사용하는이 오래된 문제에 대한 더 나은 해결책이 여기에 설명되어 있습니다.

    최신 HTML5 Server Side Events를 사용하는이 오래된 문제에 대한 더 나은 해결책이 여기에 설명되어 있습니다.

    http://www.w3schools.com/html/html5_serversentevents.asp

    예:

    http://sink.agiletoolkit.org/realtime/console

    코드 : https://github.com/atk4/sink/blob/master/admin/page/realtime/console.php#L40

    (Agile Toolkit 프레임 워크에서 모듈로 구현 됨)

  5. ==============================

    5.Windows에서 다양한 PHP 실행 명령을 시도해 본 결과 꽤 많이 달라지는 것을 발견했습니다.

    Windows에서 다양한 PHP 실행 명령을 시도해 본 결과 꽤 많이 달라지는 것을 발견했습니다.

    최상의 (가장 쉬운) 접근 방식은 다음과 같습니다.

    그래서 C ++ 프로그램에서 (다른 솔루션에 대해서는 printf 플러시 문제를 참조하십시오.)

    Logger::log(...) {
      printf (text);
      fflush(stdout);
    }
    

    PHP에서는 다음과 같은 작업을 수행합니다.

    function setupStreaming() {
        // Turn off output buffering
        ini_set('output_buffering', 'off');
        // Turn off PHP output compression
        ini_set('zlib.output_compression', false);
        // Disable Apache output buffering/compression
        if (function_exists('apache_setenv')) {
            apache_setenv('no-gzip', '1');
            apache_setenv('dont-vary', '1');
        }
    }
    function runStreamingCommand($cmd){
        echo "\nrunning $cmd\n";
        system($cmd);
    }
    ...
    
    setupStreaming();
    runStreamingCommand($cmd);
    
  6. ==============================

    6.모든 대답을 확인했지만 아무 것도 작동하지 않았습니다 ...

    모든 대답을 확인했지만 아무 것도 작동하지 않았습니다 ...

    발견 된 해결책은 여기에있다.

    그것은 Windows에서 작동합니다 (이 답변은저기서 검색하는 사용자에게 도움이된다고 생각합니다)

    <?php
    $a = popen('ping www.google.com', 'r'); 
    
    while($b = fgets($a, 2048)) { 
    echo $b."<br>\n"; 
    ob_flush();flush(); 
    } 
    pclose($a); 
    
    ?>
    
  7. ==============================

    7.먼저 flush ()가 작동하는지 확인하십시오. 그렇지 않으면 웹 서버가 어떤 이유로 버퍼링 중임을 의미합니다 (예 : mod_gzip).

    먼저 flush ()가 작동하는지 확인하십시오. 그렇지 않으면 웹 서버가 어떤 이유로 버퍼링 중임을 의미합니다 (예 : mod_gzip).

    ping과 같은 일을하는 가장 쉬운 방법은 "ping -c 1"을 여러 번 실행하고 각 출력 후에 flush ()를 호출하여 PHP 내에서 루프하는 것입니다. PHP가 사용자가 HTTP 연결을 닫을 때 (보통은 기본값이거나, ignore_user_abort (false)를 호출하여) 중단되도록 설정되었다고 가정하면, 런 - 어웨이 핑 프로세스에 대해 걱정할 필요가 없습니다 .

    자식 프로세스를 한 번만 실행하고 출력을 계속해서 표시해야하는 경우가 더 어려울 수 있습니다. 백그라운드에서 실행하고 출력을 스트림으로 리디렉션 한 다음 PHP에서 스트림을 반향시켜야합니다. 정기적 인 flush () 호출이 산재 해 있습니다.

  8. ==============================

    8.PHP를 통해 시스템 명령을 실행하려는 경우 exec 설명서를 참조하십시오.

    PHP를 통해 시스템 명령을 실행하려는 경우 exec 설명서를 참조하십시오.

    트래픽이 많은 사이트에서이 작업을 수행하지 않는 것이 좋습니다. 각 요청에 대한 프로세스를 포크하는 것은 상당한 과정입니다. 어떤 프로그램은 자신의 프로세스 ID를 파일에 기록하여 옵션을 확인하고 임의로 프로세스를 종료 할 수있는 옵션을 제공하지만 ping과 같은 명령에 대해서는 가능한지 모르지만 설명서 페이지를 확인하십시오.

    리모트 호스트에서 수신 대기중인 포트 (HTTP의 경우 포트 번호 80)에 소켓을 열면 더 나은 결과를 얻을 수 있습니다. 즉, 네트워크뿐만 아니라 사용자 영역에서도 모든 것이 잘 진행되고 있음을 알 수 있습니다.

    바이너리 데이터 출력을 php의 헤더 함수로 출력하려고한다면 적절한 content-type과 content-disposition을 설정해야합니다. 출력 버퍼 사용 / 사용 불가능에 대한 자세한 내용은 설명서를 검토하십시오.

  9. ==============================

    9.명령 줄 사용법 :

    명령 줄 사용법 :

    function execute($cmd) {
        $proc = proc_open($cmd, [['pipe','r'],['pipe','w'],['pipe','w']], $pipes);
        while(($line = fgets($pipes[1])) !== false) {
            fwrite(STDOUT,$line);
        }
        while(($line = fgets($pipes[2])) !== false) {
            fwrite(STDERR,$line);
        }
        fclose($pipes[0]);
        fclose($pipes[1]);
        fclose($pipes[2]);
        return proc_close($proc);
    }
    

    파일을 실행하려면 먼저 실행 권한을 부여해야합니다.

    chmod('/path/to/script',0755);
    
  10. ==============================

    10.php.ini 파일 세트 "output_buffering = Off"를 변경해보십시오. 페이지에서 실시간 출력을 얻을 수 있어야합니다. exec 대신 system 명령을 사용합니다. system 명령은 출력을 플러시합니다.

    php.ini 파일 세트 "output_buffering = Off"를 변경해보십시오. 페이지에서 실시간 출력을 얻을 수 있어야합니다. exec 대신 system 명령을 사용합니다. system 명령은 출력을 플러시합니다.

  11. ==============================

    11.출력을 로그 파일로 파이프 한 다음 해당 파일을 사용하여 클라이언트에 내용을 반환하는 것만으로는 안됩니다. 꽤 실시간이 아니지만 충분히 좋은 것일까 요?

    출력을 로그 파일로 파이프 한 다음 해당 파일을 사용하여 클라이언트에 내용을 반환하는 것만으로는 안됩니다. 꽤 실시간이 아니지만 충분히 좋은 것일까 요?

  12. from https://stackoverflow.com/questions/1281140/run-process-with-realtime-output-in-php by cc-by-sa and MIT license