PHP脚本在浏览器退出时没有退出


PHP script doesn't exit on browser exit

如果客户端关闭浏览器(因此连接到服务器),为什么这个虚拟脚本保持运行事件?

<>之前然而(真的){睡眠(1);file_put_contents('/tmp/foo', "I'm alive ".getmypid()."'n", FILE_APPEND);}之前这对我来说是出乎意料的。而且这个例子似乎不工作。

而带有非零参数的set_time_limit则什么也不做。

如果您尝试在该循环中向浏览器写入一些输出,您应该会发现如果连接已终止,脚本将中止。此行为在ignore_user_abort

的文档中有提示

当PHP作为命令行脚本运行时,脚本的tty显示在没有终止脚本的情况下离开,那么脚本将在下次它尝试写入任何东西时,除非value被设置为TRUE

我自己尝试了一些实验,发现即使你尝试一些浏览器输出,如果输出缓冲区还没有满,脚本也会继续运行。如果关闭输出缓冲,则在尝试输出时脚本将中止。这是有意义的- SAPI层应该注意到请求已经终止时,它试图传输输出。

这里有一个例子…

//ensure we're  not ignoring aborts..
ignore_user_abort(false);
//find out how big the output buffer is
$buffersize=max(1, ini_get('output_buffering'));

while (true)
{
    sleep( 1 );
    //ensure we fill the output buffer - if the user has aborted, then the script
    //will get aborted here
    echo str_repeat('*', $buffersize)."'n";
    file_put_contents( '/tmp/foo' , "I'm alive ".getmypid()."'n" , FILE_APPEND );
}

说明是什么触发中止。如果您的脚本容易进入无输出的无限循环,则可以使用connection_aborted()来测试连接是否仍然打开。

set_time_limit只限制在php代码中花费的时间。程序中的大部分时间(我猜>99.9%)都花在系统调用、向文件写入数据和睡眠上。

ignore_user_abort仅在您向客户端(不是在本地文件中)写入内容时才会终止——在TCP中,您根本无法区分未使用的连接和已终止的连接,除非客户端明确地使用RST数据包终止连接。