2017-02-14 14 views
0

Я хотел бы выполнить команду оболочки асинхронно в PHP. То есть PHP не должен дождаться завершения команды для продолжения выполнения. Однако, в отличие от многочисленного вопроса об этой теме в Stackoverflow, я забочусь о выходе программы. В частности, я хотел бы сделать что-то вроде этого: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(); 
} 

Приведенный выше код будет работать, если exec будет немедленно вернуться в то же время добавления элементов в массив, и если существует способ, чтобы проверить, если процесс завершается или нет ,

Есть ли способ сделать это?

+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. Лицам просто немного удобнее работать с ним. –

ответ

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

 Смежные вопросы

  • Нет связанных вопросов^_^