скрипт не продолжается после командной строки

У меня проблема со скриптом с командной строкой .. PHP скрипт никогда не продолжится ..

Попытался вызвать командную строку напрямую через putty, и она выдает много ошибок, но возвращает / завершает немедленно. Почему тогда он не возвращается обратно в PHP?

Он отлично работает с другими файлами PDF, но не с этим

http://docdro.id/b0M5vfw

$Cmd = new Command;
if($err = $Cmd->exec('/var/bin/poppler-0.51.0/utils/pdfimages -list /var/test.pdf')){
echo "ERR: $err\n";
}
echo "continue\n";
class Command {
private $descriptorspec;

private $output = '';

private $process;
private $pipes = [];

public function __construct(){
$this->descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w']  // stderr
];
}

public function output(): string{
return $this->output;
}

public function close(){
foreach($this->pipes as $pipe){
if(is_resource($pipe)){
fclose($pipe);
}
}

proc_close($this->process);
}

public function exec(string $syntax){
$this->process = proc_open($syntax, $this->descriptorspec, $this->pipes);
fclose($this->pipes[0]);

$this->output = stream_get_contents($this->pipes[1]);

$stderr = stream_get_contents($this->pipes[2]);

$this->close();

return $stderr;
}
}
# /var/bin/poppler-0.51.0/utils/pdfimages -list /var/test.pdf
page   num  type   width height color comp bpc  enc interp  object ID x-ppi y-ppi size ratio
--------------------------------------------------------------------------------------------
1     0 image    2154   303  rgb     3   8  jpeg   yes  [inline]     289   292    -    -
Syntax Error (50560): Illegal character '>'
Syntax Error (50560): Unknown operator '<10><07><82>;w<ad><a2><b4>2r<1f><10><07><8f>~j<c4>Hq<cf>Z<86>'
Syntax Error (50568): Unknown operator '<0f><b5>X<8f><ae><d0>:<d7>DU<91><cb>'v'
Syntax Error (50568): Illegal character ')'

........

Syntax Error (66698): Illegal character <04> in hex string
Syntax Error (66699): Illegal character <ff> in hex string
Syntax Error (66699): Illegal character <c1> in hex string
Syntax Error (66705): Unknown operator '<9b>'
Syntax Error (66714): Illegal character ')'
Syntax Error (66714): Unknown operator '<bc>q<ff>'
Syntax Error (66720): Unknown operator '<05>6<f8><c2><fa><d7><c3>?<f8>'
Syntax Error (66741): Unknown operator '<df><ec><99><e1>-'
Syntax Error (66743): Unknown operator ']'
Syntax Error (66762): Unknown operator '<cc>'
Syntax Error: Unterminated string
Syntax Error: End of file inside array
Syntax Error: End of file inside array
Syntax Error: Leftover args in content stream

8

Решение

PDF проблематичен — @dwarring уже ускользнул от этого в комментариях (цитируется здесь, чтобы отметить комментатора)

@dwarring сказал: «Очень быстро, я почти уверен, что этот PDF умирает, потому что поток контента содержит встроенное изображение, начинающееся с« BI », за которым следуют случайные данные и заканчивающиеся« EI ». Инженеры Adobe В тот день, когда они разработали эти операторы, проблема заключается в том, что возникают ситуации, когда двоичные данные случайным образом содержат «EI» и делают PDF-файл не разбираемым. Некоторые инструменты могут справиться с этим лучше, но в идеале производитель этого изображения должен избегать использования встроенных изображений. «

С точки зрения PHP, однако, вместо оператора if используйте блок try / catch, и вы должны сохранить контроль над сценарием.

$Cmd = new Command;

try {
$err = $Cmd->exec('/var/bin/poppler-0.51.0/utils/pdfimages - list/var/test.pdf')){
} catch (Exception $e) {
var_log($e);
}

echo "continue\n";
7

Другие решения

Вы могли бы использовать stream_select в сочетании с feof чтобы проверить, какой из двух потоков чтения имеет доступные данные, как в следующем коде.

Я протестировал его (используя PHP 7), и он не блокируется здесь (с внесенными изменениями).

    public function exec(string $syntax){
$this->process = proc_open($syntax, $this->descriptorspec, $this->pipes);
fclose($this->pipes[0]);

$stderr = "";

$num_changed_streams = NULL;
while (!feof($this->pipes[1]) || !feof($this->pipes[2])) {
$read = [$this->pipes[1], $this->pipes[2]];
$write = NULL;
$err = NULL;
$num_changed_streams = stream_select($read, $write, $err, 3);
if ($num_changed_streams === false) {
$this->close();
return $stderr;
} else {
if (isset($read[0])) {
$this->output .= stream_get_contents($read[0]);
echo "output: {$this->output} ";
}
if (isset($read[1])) {
$stderr .= stream_get_contents($read[1]);
echo "stderr: {$stderr}";
}
}
}
$this->close();
return $stderr;
}

stream_select а также feof функции необходимы из-за следующего (цитируется из http://php.net/manual/en/function.stream-select.php):

Потоки, перечисленные в массиве read, будут отслеживаться, чтобы увидеть, станут ли символы доступными для чтения (точнее, посмотреть, не заблокируется ли чтение — в частности, ресурс потока также готов к концу файла, в этом случае fread () вернет строку нулевой длины).

0

Проблема в том, что эта программа /var/bin/poppler-0.51.0/utils/pdfimages ничего не пишет в stdout и ваш код висит на $this->output = stream_get_contents($this->pipes[1]); следовательно, ваш класс не подходит для этой программы. Для программ, которые ничего не пишут stdout вы не должны читать из $this->pipes[1], У вас должен быть другой класс, который используется для этого конкретного типа приложений:

class CommandWithNoOutput {
private $descriptorspec;

private $process;
private $pipes = [];
private $output = '';

public function __construct(){
$this->descriptorspec = [
0 => ['pipe', 'r'], // stdin
1 => ['pipe', 'w'], // stdout
2 => ['pipe', 'w']  // stderr
];
}

public function output(): string{
return (string)$this->output;
}public function close(){
foreach($this->pipes as $pipe){
if(is_resource($pipe)){
fclose($pipe);
}
}

proc_close($this->process);
}

public function exec($syntax){

$this->process = proc_open($syntax, $this->descriptorspec, $this->pipes);
fclose($this->pipes[0]);

$stderr = stream_get_contents($this->pipes[2]);

$this->close();

$this->output = ob_get_clean();

return $stderr;
}
}

$Cmd = new CommandWithNoOutput;
if($err = $Cmd->exec('/usr/bin/pdfimages -list test.pdf')){
echo "ERR: $err\n";
}
echo "continue\n";

Этот код выводит это:

ERR: Syntax Error (50560): Illegal character '>'
Syntax Error (50560): Unknown operator '<10><07><82>;w<ad><a2><b4>2r<1f><10><07><8f>~j<c4>Hq<cf>Z<86>'
Syntax Error (50568): Unknown operator '<0f><b5>X<8f><ae><d0>:<d7>DU<91><cb>'v'
Syntax Error (50568): Illegal character ')'
Syntax Error (50570): Unknown operator '<15><c7>=j<c4>X<f4><e8>'
.....a lot of errors.....
Syntax Error (66762): Unknown operator '<cc>'
Syntax Error: Unterminated string
Syntax Error: End of file inside array
Syntax Error: End of file inside array
Syntax Error: Leftover args in content stream

continue

Process finished with exit code 0

ОБНОВИТЬ:
Другое решение — позвонить stream_set_blocking($this->pipes[1], 0); сразу после звонка proc_open поэтому код не будет ждать никакого вывода.

0
По вопросам рекламы [email protected]