proc_open hangs when trying to read from a stream
在尝试使用
基本上我的代码如下:
1 2 3 4 5 6 7 8 9 10 | $descriptorspec = array ( array("pipe","r"), array("pipe","w"), array("pipe","w") ); $pipes = array(); $procedure = proc_open('cd"C:/Program Files/ffmpeg/bin" &&"ffmpeg.exe" -i"C:/wamp/www/project/Wildlife.wmv" -deinterlace -qdiff 2 -ar 22050"C:/wamp/www/project/Wildlife.flv"', $descriptorspec, $pipes); var_dump(stream_get_contents($pipes[1])); |
现在,此代码将导致PHP无限期挂起(如果使用
造成这种情况的原因(我怀疑)是,尽管STDOUT流已成功打开,但该进程未向其中写入任何内容(即使在cmd中运行了相同的命令也会显示输出),因此,试图从该流中读取内容,将会导致与此处所述相同的问题,因此-PHP等待流中包含任何内容,进程未向其中写入任何内容。
但是(额外的乐趣),设置
这样-有人可以确认/否认正在发生的事情,并在可能的情况下显示我如何应对这种情况?我看过PHP错误,所有
我暂时已经实现了这样的解决方案:
1 2 3 4 5 6 7 8 9 | $timeout = 60; while (true) { sleep(1); $status = proc_get_status($procedure); if (!$status['running'] || $timeout == 0) break; $timeout--; } |
但是,我真的不想依赖这样的东西:
另外,我真的不想等待一整分钟的时间来检查该过程(例如,从命令行转换给定的视频需要不到10秒的时间),而我将需要花费更多时间来转换视频。
根据@Sjon的评论,这是我使用的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | $descriptorspec = array ( array("pipe","r"), array("pipe","w"), array("pipe","w") ); $pipes = array(); $procedure = proc_open('cd"C:/Program Files/ffmpeg/bin" &&"ffmpeg.exe" -i"C:/wamp/www/sandbox/Wildlife.wmv" -deinterlace -qdiff 2 -ar 22050"C:/wamp/www/sandbox/Wildlife.flv"', $descriptorspec, $pipes); $read = array($pipes[0]); $write = array($pipes[1], $pipes[2]); $except = array(); while(true) if(($num_changed_streams = stream_select($read, $write, $except, 10)) !== false) { foreach($write as $stream) var_dump(stream_get_contents($stream)); exit; } else break; |
与@Sjon的每次对话-从Windows上的缓冲流读取均已中断。最后的解决方案是通过外壳使用流重定向,然后读取创建的文件-这样
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | $descriptorspec = array ( array("pipe","r"), array("pipe","w"), array("pipe","w") ); $pipes = array(); $procedure = proc_open('cd"C:/Program Files/ffmpeg/bin" &&"ffmpeg.exe" -i"C:/wamp/www/sandbox/Wildlife.mp4" -deinterlace -qdiff 2 -ar 22050"C:/wamp/www/sandbox/Wildlife.flv"> C:/stdout.log 2> C:/stderr.log', $descriptorspec, $pipes); proc_close($procedure); $output = file_get_contents("C:/stdout.log"); $error = file_get_contents("C:/stderr.log"); unlink("C:/stdout.log"); unlink("C:/stderr.log"); |
当流被缓冲时,在文件中,我们将获得无缓冲的输出(我也是这样做的)。而且,由于外壳程序的结果是无缓冲且同步的,因此我们不需要检查文件是否更改。
复制花了一些时间,但我发现了您的问题。您运行的命令在运行时会输出一些诊断信息。但它不会输出到stdout,而是输出到stderr。
Under normal circumstances every UNIX program has three streams opened for it when it starts up, one for input, one for output, and one for printing diagnostic or error messages
如果您可以正确使用流;这不是问题。但是您改为调用
要扩展对问题的添加stream_select;在php的Windows中未实现stream_select,它在手册中这样说:
Use of stream_select() on file descriptors returned by proc_open() will fail and return FALSE under Windows.
因此,如果上面发布的代码不起作用;我不确定会怎样。您是否考虑过放弃流解决方案,而是恢复为简单的exec()调用?如果将