最近有个项目需要在服务器端运行很长时间,由于安全的问题,现在不允许直接登录到服务器在控制台下执行程序,这样一来就很难准确知道程序的进度。于是就想要是PHP能够把输出实时发送到客户端就好了,以前一直以为这是不行的,后来实验了一把,发现是可以做到的:
实验环境:(Apache, mod_php, nc, curl)
数据从Apache发送到用户代理,一般要涉及到三个缓冲(Buffer):PHP输出缓冲、Apache输出缓冲、用户代理的缓冲。因此,只要禁用或者实时刷新这几个缓冲,就可以把PHP的输出实时的显示。
PHP的输出缓冲可以通过 ob_start() 或者 ini 中的 output.buffering 来启用,缓冲的刷新可以用 ob_flush() 实现
Apache 的输出缓冲在 PHP 中可以通过 flush() 来刷新
用户代理方面的缓冲我们可以通过使用无缓冲的代理(nc)或者禁用缓冲(curl -N)
了解了上面这些内容,实时输出的程序就很容易实现了:
while (1) {
echo '.';
ob_flush();
flush();
}
如果 php.ini 中 output.buffering 没有打开的话,ob_flush() 也是没有必要的。而且 ob_flush() 和 flush() 的调用顺序也是有顺序要求的,现调用 ob_flush() 把 php 缓冲的内容刷新到 apache 的缓冲,然后再刷新 apache 的缓冲。
另外,apache的一些模块(mod_gzip)有可以改写apache的缓冲策略导致 php 的 flush() 函数失效,对待这样的情况我们需要另想办法;大部分的浏览器都是有缓冲的,因此可能无法实时显示接收的数据。