脚本不会在命令行之后继续



我在带有命令行的脚本中有问题。PHP脚本永远不会继续。

试图通过腻子直接调用命令行,并且它输出了很多错误,但返回/立即完成。为什么不回到php?

它可以与其他PDF文件一起使用,但这不是一个

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: $errn";
}
echo "continuen";

class

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

pdf是有问题的 - @dwarring已经在评论中对此进行了避免(在此处引用以归功于评论者)

@dwarring说:"很快,我很确定该PDF正在死亡,因为内容流包含启动的内联图像和'bi',然后是随机数据,然后以'ei'结束。当他们设计这些操作员时,有一个问题是出现的情况是,二进制数据随机包含" 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 "continuen";

您可以将stream_selectfeof结合使用来检查两个读取流中的哪个具有可用数据,例如以下代码。

我已经对其进行了测试(使用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_selectfeof功能(引用http://php.net/manual/enual/en/function.stream-select.php):

将观看读取数组中列出的流以查看字符是否可用于阅读(更确切地说,查看读取是否不会阻止 - 特别是,尤其是在文件结束时也可以准备好,在这种情况下

问题是该程序/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: $errn";
}
echo "continuen";

此代码输出以下内容:

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

更新:另一个解决方案是在致电proc_open之后立即致电stream_set_blocking($this->pipes[1], 0);,以便代码不等待任何输出。

相关内容

  • 没有找到相关文章