我的脚本有一个命令行有问题.PHP脚本永远不会继续..
试图直接通过putty调用命令行,它输出很多错误但是立即返回/完成。为什么不返回PHP?
它适用于其他PDF文件,但不适用于此
$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
答案 0 :(得分:7)
PDF存在问题 - @dwarring已经在评论中提到了这一点(此处引用以表达对评论者的评价)
@dwarring说“很快,我很确定这个PDF正在死亡,因为内容流包含一个内联图像,由''BI'跟随随机数据,以'EI'结束.Adobe工程师正在在他们设计这些操作符的关闭日期,问题在于二进制数据随机包含“EI”并使PDF无法解析的情况出现。有些工具可能会更好地处理这个问题,但理想情况下,此图像的制作者应避免使用内联图片。“
从PHP方面来说,使用try / catch块而不是if语句,你应该保留对脚本的控制。
$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";
答案 1 :(得分:0)
您可以将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;
}
由于以下内容(引自http://php.net/manual/en/function.stream-select.php),因此需要stream_select
和feof
个函数:
将监视读取数组中列出的流以查看字符是否可用于读取(更准确地说,查看读取是否不会阻塞 - 特别是,流资源在文件末尾也已准备就绪,在这种情况下,fread()将返回零长度字符串。)
答案 2 :(得分: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
,这样代码就不会等待任何输出。