PHP的`flush()`在从终端/命令行运行时是否有任何作用?

huangapple go评论50阅读模式
英文:

Does PHP's flush() do anything if running from terminal/cli?

问题

我直接从终端启动PHP并传递一个.php脚本来运行,不使用Web浏览器。

flush()的文档中说:

刷新PHP的系统写入缓冲区以及PHP所使用的后端(CGI、Web服务器等)。这试图将当前的输出尽可能推送到浏览器,但有一些注意事项。

基于此,根据它所说的“PHP的系统写入缓冲区”,似乎可能在需要在脚本结束之前立即将输出发送到终端时仍然需要使用flush()。但我想要明确知道。我目前使用的是PHP 8.1,但我的问题希望不仅适用于特定版本。

我想从熟悉PHP的C实现的人那里了解,是否有任何情况下在从终端启动PHP时会缓冲输出,或者只有在服务器通过特殊方式启动PHP时才会发生这种情况。我知道如果运行故意请求缓冲的代码,例如使用ob_start()或类似的内容,那么它应该进行缓冲,调用flush()不会结束缓冲,但这不是我要问的。我问的是不明确请求任何缓冲的代码。

英文:

I'm starting php directly from the terminal and passing it a .php script to run, I'm not using a web browser.

The documentation for flush() says

> Flushes the system write buffers of PHP and whatever backend PHP is
> using (CGI, a web server, etc). This attempts to push current output
> all the way to the browser with a few caveats.

So based on that, it sounds possible that flush() could still be needed when you need output to immediately get sent to the terminal before the script ends, because of the part where it said "system write buffers of PHP". But I would like to know definitively. I'm using php 8.1 currently, but my question is hopefully not version specific.

I'm wanting to know from someone familiar with PHP's C implementation whether it ever under any circumstances buffers output when started from a terminal, or if that only happens if PHP is started a special way by a server. I know if I run code that intentionally requests buffering by using ob_start() or something like that, then it is supposed to buffer and this will not be ended by calling flush(), that's not what I'm asking about. I'm asking about code that doesn't explicitly request any buffering.

答案1

得分: 1

请注意,以下是代码的翻译部分:

// ob_start();

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

请注意,这只是代码的翻译部分,不包括注释或其他文本。

英文:

Why not test that yourself?

<?php

// ob_start();

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

On my test terminal (standard Ubuntu 20.04.5 LTS), ob_start buffers everything, and ignores flush() altogether. Without ob_start, all text is output immediately (even if not ended by a LF, as is the case for the second test).

I haven't a PHP 8.1 handy, but mine says,

> 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

You might ask a different (opposite, even) question: are there conditions whereby my terminal-run script might start buffering for some reason?

When you call flush() the call gets ultimately redirected to sapi_module, which issues a fflush() on stdout (this on the current source tree on Github, but I don't think this was changed since at least PHP 5). This is enough, I believe, to say that flush() is sufficient.

Is it necessary? On a standard run from the terminal, no. But I didn't include any scriptlets or libraries or Composer modules that might have changed the buffering strategy.

Of course, any of those could have. Just issue an ob_start() (maybe because the module is born to run on a web server) and hey presto!, your script starts buffering and requires flush (actually, in that case, ob_flush() - as said above, flush will not work).

But if that's the case, you've got a completely different beast to deal with - you should probably write your own output function, so that all console writes are routed to some code that can check, say, ob_get_level() and deal with it accordingly. Or, bringing this to the extreme,

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

huangapple
  • 本文由 发表于 2023年2月19日 06:57:50
  • 转载请务必保留本文链接:https://go.coder-hub.com/75496889.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定