我有一个执行shell命令的PHP脚本:
$handle = popen('python last', 'r'); $read = fread($handle, 4096); print_r($read); pclose($handle);
我回应了shell输出的输出.当我在命令中运行它时,我得到这样的东西:
[root@localhost tester]# python last [last] ZVZX-W3vo9I: Downloading video webpage [last] ZVZX-W3vo9I: Extracting video information [last] ZVZX-W3vo9I: URL: x [download] Destination: here.flv [download] 0.0% of 10.09M at ---b/s ETA --:-- [download] 0.0% of 10.09M at 22.24k/s ETA 07:44 [download] 0.0% of 10.09M at 66.52k/s ETA 02:35 [download] 0.1% of 10.09M at 154.49k/s ETA 01:06 [download] 0.1% of 10.09M at 162.45k/s ETA 01:03
但是,当我从PHP运行相同的命令时,我得到这个输出:
[last] ZVZX-W3vo9I: Downloading video webpage [last] ZVZX-W3vo9I: Extracting video information [last] ZVZX-W3vo9I: URL: x [download] Destination: here.flv
正如你所看到的那样,我想要的位是丢失的!之前的问题是百分比在同一行上更新,但现在我已经更改了我的Python脚本,以便创建一个新行.但这有所不同!:(
这一问题与这一个.
感谢您的任何帮助.
需要重定向输出"2>&1".Arul很幸运:P因为我错过了截止日期来选择属于Pax的真正答案!
您只读取管道中的前4,096个字节,您需要将fread
/ print
_r置于循环中并使用该feof
函数检查文件结尾.
$handle = popen('python last', 'r'); while(!feof($handle)) { print_r(fread($handle, 4096)); } pclose($handle);
第一步是查看输出的去向.我要做的第一件事是选择一个稍微小一点的文件,这样你就不会在每次测试中等待七分钟.
第1步/查看shell中的内容写入位置.执行命令python last >/tmp/stdout 2>/tmp/stderr
然后查看这两个文件.理想情况下,所有内容都将写入stdout,但情况可能并非如此.这为您提供了脚本的基线行为.
第2步/使用PHP从PHP运行时做同样的事情$handle = popen('python last >/tmp/stdout 2>/tmp/stderr', 'r');
.在这种情况下,您的PHP脚本可能不会返回任何内容,但仍应填充文件.这将捕获在非终端环境中运行时的任何更改行为.
如果某些输出转到stderr,那么解决方案就应该如此简单 $handle = popen('python last 2>&1', 'r');
另外,PHP的doco状态(我的粗体):
Returns a file pointer identical to that returned by fopen(), except that it is unidirectional (may only be used for reading or writing) and must be closed with pclose(). This pointer may be used with fgets(), fgetss(), and fwrite().
所以我不确定你是否应该使用fread()
它,尽管它在其中一个例子中显示.不过,我认为基于行的输入更多地映射到您想要实现的目标.
无论如何,您应该在循环中读取输出,以确保在超过4K时可以获得输出,例如:
$handle = popen ('python last 2>&1', 'r'); if ($handle) { while(! feof ($handle)) { $read = fgets ($handle); echo $read; } pclose ($handle); }
需要注意的另一件事是,如果您输出的是浏览器并且需要很长时间,浏览器本身可能会超时,因为它认为服务器端连接已经消失.如果您发现一个小文件正常工作且您的10M/1分钟文件无法正常工作,则可能就是这种情况.您可以尝试,flush()
但并非所有浏览器都会尊重这一点.
这样做要容易得多:
$output = `python last`; var_dump($output);
'ticks'(`)将执行该行并捕获输出.这是一个测试示例:
文件test.php:
文件capture.php:
从php capture.php输出:
string(80) "Test PHP Script Test PHP Script Test PHP Script Test PHP Script Test PHP Script "
然后,您可以根据换行符将输出拆分为数组:
$outputArray = explode('\n', $output);
或者使用proc_open(),它可以提供比popen更多的控制,因为您可以指定要处理stdin,stdout和stderr的位置.
或者你可以fopen STDIN
或php://stdin
然后管道到PHP:
? python last | php script.php
我会选择1并使用反引号,最简单的方法.