PHP读取shell_exec实时输出
我只是在Linux服务器上试用PHP和PHP读取shell_exec实时输出,php,Php,我只是在Linux服务器上试用PHP和shell\u exec。这是一个非常酷的功能使用,我真的很喜欢到目前为止。有没有办法查看命令运行时正在进行的实时输出 例如,如果在ping目标地址时运行了ping stackoverflow.com,那么每次ping时都会使用PHP显示结果?可能吗 我希望看到缓冲区运行时的实时更新。也许这是不可能的,但肯定会很好 这就是我正在尝试的代码,我尝试过的每一种方法都会在命令完成后显示结果 <?php $cmd = 'ping -c 10 127.0.
shell\u exec
。这是一个非常酷的功能使用,我真的很喜欢到目前为止。有没有办法查看命令运行时正在进行的实时输出
例如,如果在ping目标地址时运行了ping stackoverflow.com
,那么每次ping时都会使用PHP显示结果?可能吗
我希望看到缓冲区运行时的实时更新。也许这是不可能的,但肯定会很好
这就是我正在尝试的代码,我尝试过的每一种方法都会在命令完成后显示结果
<?php
$cmd = 'ping -c 10 127.0.0.1';
$output = shell_exec($cmd);
echo "<pre>$output</pre>";
?>
我试着把echo
部分放在一个循环中,但仍然没有成功。有没有人建议让它在屏幕上显示实时输出,而不是等到命令完成
我试过
exec
,shell\u exec
,system
和passthru
。每个人都会在完成后显示内容。除非我使用了错误的语法或者我没有正确设置循环。要读取进程的输出,popen()
。您的脚本将与程序并行运行,您可以通过读取和写入它的输出/输入来与它交互,就像它是一个文件一样
但是,如果您只想将结果直接转储给用户,您可以直接使用passthru()
:
echo';
passthru($cmd);
回声';
如果要在程序运行时显示输出,可以执行以下操作:
$result = liveExecuteCommand('ls -la');
if($result['exit_status'] === 0){
// do something if command execution succeeds
} else {
// do something on failure
}
while(@ob_end_flush());//结束所有输出缓冲区(如果有)
$proc=popen($cmd,'r');
回声';
而(!feof($proc))
{
echo-fread($proc,4096);
@冲洗();
}
回声';
这段代码应该运行该命令,并在运行时将输出直接推送到最终用户。首先,感谢Havenard提供的代码片段,它帮助了很多 哈夫纳德代码的一个稍加修改的版本,我发现它很有用
如果您愿意下载依赖项,请执行此操作。我发现使用这个清洁器的界面比自己用
popen()
或passthru()
重新发明任何东西都好
这由Symfony文档提供:
您还可以将Process类与foreach构造一起使用来获取
生成时的输出。默认情况下,循环等待新的
在进入下一个迭代之前输出:
作为警告,PHP和Nginx在将输出发送到浏览器之前尝试缓冲时遇到了一些问题。您可以通过在PHP.ini中关闭输出缓冲来禁用PHP中的输出缓冲:output\u buffering=off
。显然有很多问题,但为了避免麻烦,我最终使用了PHP内置服务器进行测试
我在Gitlab上给出了一个完整的例子:为什么不先在shell中执行该文件?使用passthru()而不是shell_exec(),我现在就研究passthru。我在研究passthru()的时候发现了一个类似的代码,但我一定把它搞糟了。我试了大约一个小时让它工作。谢谢你,这正是我想要的,工作完美。是的,诀窍是强制执行根本不会发生缓冲。这段代码确保了这一点。通常,PHP只会在累积至少4KB的数据时刷新输出。从python进程捕获输出时,需要禁用输出缓冲:python-u/path/to/watch。。。或者PYTHONUNBUFFERED=1 watch…@erikvande即使在这种情况下,您也可能希望查看
mkfifo()
。如果您在Nginx中,您还应该添加头('X-Accel-Buffering:no')
以确保针对单个响应关闭gzip和fastcgi_缓冲。我想知道为什么这段代码不起作用,这就是为什么。对于整个.sh脚本,这段代码能起作用吗?我想得到一个从PHP调用的.sh脚本的即时反馈?请看我的问题:它会起作用的。类似于:liveExecuteCommand(“sh/path/to/script.sh”);好极了这正是我想要的。不过有一个小建议:在exit_状态下抛出一个intval(…),以整数而不是字符串的形式返回。非常有用。请不要使用尾随分号编写shell命令,否则exit_状态将始终为0。是的,在Nginx中,您还应该执行头('X-Accel-Buffering:no')
以确保针对单个响应关闭gzip和fastcgi_缓冲,而不是针对所有请求关闭它。我花了太长时间才弄明白。
while (@ ob_end_flush()); // end all output buffers if any
$proc = popen($cmd, 'r');
echo '<pre>';
while (!feof($proc))
{
echo fread($proc, 4096);
@ flush();
}
echo '</pre>';
<?php
/**
* Execute the given command by displaying console output live to the user.
* @param string cmd : command to be executed
* @return array exit_status : exit status of the executed command
* output : console output of the executed command
*/
function liveExecuteCommand($cmd)
{
while (@ ob_end_flush()); // end all output buffers if any
$proc = popen("$cmd 2>&1 ; echo Exit status : $?", 'r');
$live_output = "";
$complete_output = "";
while (!feof($proc))
{
$live_output = fread($proc, 4096);
$complete_output = $complete_output . $live_output;
echo "$live_output";
@ flush();
}
pclose($proc);
// get exit status
preg_match('/[0-9]+$/', $complete_output, $matches);
// return exit status and intended output
return array (
'exit_status' => intval($matches[0]),
'output' => str_replace("Exit status : " . $matches[0], '', $complete_output)
);
}
?>
$result = liveExecuteCommand('ls -la');
if($result['exit_status'] === 0){
// do something if command execution succeeds
} else {
// do something on failure
}
$process = new Process('ls -lsa');
$process->start();
foreach ($process as $type => $data) {
if ($process::OUT === $type) {
echo "\nRead from stdout: ".$data;
} else { // $process::ERR === $type
echo "\nRead from stderr: ".$data;
}
}