PHP的flush()在终端/cli运行时有什么作用吗?

dohp0rv5  于 2023-02-21  发布在  PHP
关注(0)|答案(1)|浏览(110)

我直接从终端启动php,并传递一个.php脚本来运行,我没有使用网络浏览器。
documentation for flush()表示
刷新PHP的系统写缓冲区和任何PHP正在使用的后端(CGI,web服务器等)。这试图将当前输出一直推到浏览器,但有一些警告。
基于此,当你需要输出在脚本结束前立即发送到终端时,可能仍然需要flush(),因为有部分写着“PHP的系统写缓冲区”。但我想确切地知道。我目前使用的是php 8.1,但我的问题希望不是特定版本的。
我想从一个熟悉PHP的C实现的人那里知道,当从终端启动时,它是否在任何情况下都会缓冲输出,或者只有当服务器以特殊方式启动PHP时才会发生这种情况。我知道,如果我运行的代码故意使用ob_start()或类似的东西来请求缓冲,那么它应该缓冲,而这不会通过调用flush()来结束。我问的不是这个,我问的是那些没有明确请求缓冲的代码。

yzuktlbb

yzuktlbb1#

为什么不自己试试呢?

<?php

// ob_start();

print "Test 1\n";
sleep(1);
print "Test 2";
sleep(5);
print "Test 3";
flush();
sleep(5);

在我的测试终端(标准Ubuntu 20.04.5 LTS)上,ob_start缓冲 * 所有内容 *,并完全忽略flush(),如果没有ob_start,所有文本都会立即输出(即使没有以LF结尾,如第二个测试)。
我手边没有PHP 8.1,但我的PHP 8.1说,

> PHP 8.2.1 (cli) (built: Jan 18 2023 10:17:15) (NTS)
> Copyright (c) The PHP Group
> Zend Engine v4.2.1, Copyright (c) Zend Technologies

你可以问一个 * 不同 (相反,甚至)的问题: 是否存在终端运行脚本可能因某种原因开始缓冲的情况?*
当你调用flush()时,调用最终会被重定向到sapi_module,它会在stdout上发出一个fflush()(这在Github上的the current source tree上,但我不认为 * 这 * 至少在PHP 5之后有所改变)。
有必要吗?在终端的标准运行中,没有。但是我没有包括任何脚本、库或Composer模块,这些模块可能会改变缓冲策略。
当然,任何一个都可以,只要发出一个ob_start()(可能是因为模块天生就运行在Web服务器上),然后嘿,很快,你的脚本就开始缓冲,并需要flush(实际上,在这种情况下,ob_flush()-如上所述,flush将无法工作)。
但如果是这样的话,您就有了一个完全不同的问题要处理--您可能应该编写自己的输出函数,以便所有控制台写入都被路由到某个代码,该代码可以检查(比如ob_get_level())并相应地处理它。

declare(ticks=1);
register_tick_function(static function() {
    ob_get_level() && ob_flush();
    flush();
});

相关问题