2017-02-14 16 views
0

PHP에서 쉘 명령을 비동기 적으로 실행하고 싶습니다. 나는. PHP는 실행을 계속하기 위해 명령이 완료되기를 기다리지 않아야합니다. 그러나 Stackoverflow에서 그 주제에 관한 수많은 질문과는 달리 나는 프로그램의 출력에 관심이 있습니다. 특히이 같은 것을 할 싶습니다 여전히 배열에 요소를 추가하는 동안 exec 즉시 반환하는 경우 위의 코드가 작동 할PHP 쉘 명령을 비동기 적으로 실행하고 실시간 출력을 검색하십시오.

exec("some command", $output_array, $has_finished); 
while(count($output_array) > 0 && !$has_finished) 
{ 
    if(count($output_array) > 0) 
    { 
     $line = array_shift($output_array); 
     do_something_with_that($line); 
    } else 
     sleep(1); 
} 

do_something_with_that($line) 
{ 
    echo $line."\n"; 
    flush(); 
} 

을 프로세스가 종료되거나하지 않은 경우 확인하는 방법이 있다면 .

할 방법이 있습니까?

+0

https://github.com/clue/php-shell-react 또는 당신은 않는 스레드를 생성 할 수 있습니다 –

+0

유사 그 스레드의 상태를 확인하십시오. 아마 당신이 확인할 수있는 많은 자원이 있습니다. 그러나 네이티브 PHP에서는 이것을 할 수 없으며 모듈이나 라이브러리가 필요합니다. – apokryfos

+0

@apokryfos [proc_open] (http://php.net/manual/en/function.proc-open.php)은 매우 기본적인 PHP 기능입니다. Libs는 작업하기가 좀 더 편리합니다. –

답변

0

출력 STDIN을 임시 파일로 파이핑 한 다음 파일에서 읽음으로써이 문제를 해결했습니다.

여기

class ExecAsync { 

    public function __construct($cmd) { 
     $this->cmd = $cmd; 
     $this->cacheFile = ".cache-pipe-".uniqid(); 
     $this->lineNumber = 0; 
    } 

    public function getLine() { 
     $file = new SplFileObject($this->cacheFile); 
     $file->seek($this->lineNumber); 
     if($file->valid()) 
     { 
      $this->lineNumber++; 
      $current = $file->current(); 
      return $current; 
     } else 
      return NULL; 
    } 

    public function hasFinished() { 
     if(file_exists(".status-".$this->cacheFile) || 
      (!file_exists(".status-".$this->cacheFile) && !file_exists($this->cacheFile))) 
     { 
      unlink($this->cacheFile); 
      unlink(".status-".$this->cacheFile); 
      $this->lineNumber = 0; 
      return TRUE; 
     } else 
      return FALSE; 
    } 

    public function run() { 
     if($this->cmd) { 
      $out = exec('{ '.$this->cmd." > ".$this->cacheFile." && echo finished > .status-".$this->cacheFile.";} > /dev/null 2>/dev/null &"); 
     } 
    } 
} 

사용 내

구현의

$command = new ExecAsync("command to execute"); 
//run the command 
$command->run(); 
/*We want to read from the command output as long as 
*there are still lines left to read 
*and the command hasn't finished yet 

*if getLine returns NULL it means that we have caught up 
*and there are no more lines left to read 
*/ 
while(($line = $command->getLine()) || !$command->hasFinished()) 
{ 
    if($line !== NULL) 
    { 
     echo $line."\n"; 
     flush(); 
    } else 
    { 
     usleep(10); 
    } 
}