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

PHP脚本没有';t在浏览器退出时退出,php,termination,Php,Termination,如果客户端关闭浏览器(以便连接到服务器),为什么此虚拟脚本会继续运行事件 while(true) { 睡眠(1); 文件内容('/tmp/foo',“我还活着”.getmypid()。“\n”,文件附加); } 这对我来说是出乎意料的。同样,这个例子似乎不起作用 对于一个非零参数,什么也不做 我需要一些澄清。如果您尝试在该循环中向浏览器写入一些输出,您应该会发现,如果连接已终止,脚本将中止。此行为在以下文档中有所暗示: 当将PHP作为命令行脚本运行时,脚本的tty 如果脚本没有终止,那么脚本将在

如果客户端关闭浏览器(以便连接到服务器),为什么此虚拟脚本会继续运行事件

while(true) { 睡眠(1); 文件内容('/tmp/foo',“我还活着”.getmypid()。“\n”,文件附加); } 这对我来说是出乎意料的。同样,这个例子似乎不起作用

对于一个非零参数,什么也不做


我需要一些澄清。

如果您尝试在该循环中向浏览器写入一些输出,您应该会发现,如果连接已终止,脚本将中止。此行为在以下文档中有所暗示:

当将PHP作为命令行脚本运行时,脚本的tty 如果脚本没有终止,那么脚本将在 下次它尝试写入任何内容时,除非值设置为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 );
}
这演示了触发中止的原因。如果您的脚本很容易进入无输出的无休止循环,那么可以使用它来测试连接是否仍然打开。

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


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

这解释了
设置时间限制
,写入某些内容不会做出任何更改。需要写入输出以触发用户中止感测IIRC。-@是的,当然随机本地文件对TCP连接没有影响。更新了。@cYrus:你试过什么了。请在问题代码中反映这一点。您需要禁用忽略用户中止。默认设置是在IIRC上。@Paul:谢谢,它能工作!但有些数据确实是通过这种方式从服务器发送到客户端的吗?不,因为连接被中止了!我在上面演示的是,在SAPI层尝试刷新缓冲区之前,脚本不会中止。如果您有特定的原因要检查客户端中止,请检查connection_aborted(),我的意思是在中止之前(客户端关闭浏览器)。好的,根据wireshark实际发送的数据:
*…
。无论如何,这可以解决我的问题,谢谢!您忽略了用户中止,而没有向客户端进行任何类型的输出。
//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 );
}