即使在关闭页面后,脚本是否仍会继续运行


Will a script continue to run even after closing a page?

如果我通过jquery ajax调用一个php文件,其中包含一个脚本来做一些需要一段时间的事情 - 例如上传一个大视频 - 然后我关闭页面:php脚本是否继续加载视频?

看这里:http://php.net/manual/en/function.ignore-user-abort.php

int ignore_user_abort ([ bool $value ] )

设置客户端断开连接是否应导致脚本中止。

当将PHP作为命令行脚本运行时,脚本的tty消失而没有终止脚本,那么脚本将在下次尝试写入任何内容时死亡,除非值设置为TRUE。

还有一个同名的 PHP 配置选项:http://php.net/manual/en/misc.configuration.php

默认情况下,如果您什么都不做,根据 PHP 手册,默认值是中止脚本。http://php.net/manual/en/features.connection-handling.php

必要的更新

似乎我(不知不觉地)欺骗了我的方式获得了"声誉点",因为我没有提供(正确)答案,但现在这要归功于"mellamokb"的测试和持续推动:

报价:"好的,我看了一下PHP源代码,如果我没有错过任何东西,我现在有了答案。仅当 PHP 收到尝试向用户输出内容的错误时,才会检查"ignore_user_abort"标志。因此,在我的理解中,没有办法中断不产生任何输出的代码。

好吧,我并没有完全关闭,但重要的是要知道这完全取决于您的脚本是否产生了任何输出!

如果您阅读此内容,也请查看下面的评论。

通过 Web 服务器运行的 PHP 脚本不会停止,直到:

  • 有人杀死了服务器
  • 服务器杀死 PHP Scrip

当用户中止脚本时,PHP 将继续,直到它尝试将内容发送回浏览器。

例如,即使用户中止,脚本仍将永远继续:

while(true){
    echo 'go'.PHP_EOL;
}

它将永远持续下去,因为"echo"将写入缓冲区,并且在脚本完成之前缓冲区不会发送到浏览器,这永远不会发生。

以下脚本将在用户中止后立即停止:

while(true){
    echo 'go'.PHP_EOL;
    flush();
    ob_flush();
}

此脚本将停止,因为 flush() 和 ob_flush() 将强制 PHP 将其缓冲区发送到浏览器,如果用户中止,浏览器将停止 PHP 脚本。在这种情况下,函数 ignore-user-abort() 将强制 PHP 忽略中止。

此外,如果您使用的是PHP会话,则它们是另一种棘手的情况。例如,如果您正在执行 AJAX,并且您实际上向 PHP 脚本发送了两个 AJAX 请求,并且该 PHP 脚本需要与 session_start() 进行会话。第一个 AJAX 查询将正常工作,但是第二个查询必须等到第一个调用完成,因为第一个脚本在会话上已锁定。第一个脚本最终可能会过早地使用 session_write_close() 释放会话;

默认情况下没有。请参阅连接处理文档,特别是:

您可以决定是否要 客户端断开连接导致 要中止的脚本。有时是 方便始终运行脚本 即使没有完成 接收输出的远程浏览器。 但是,默认行为是 您的脚本在 远程客户端断开连接。

脚本

将运行max_execution_time设置的时间(默认为 30s)

警告 当 PHP 在安全模式下运行时,此函数不起作用。 除了关闭安全模式或更改 PHP 中的时间限制.ini。 注意:set_time_limit() 函数和 配置指令max_execution_time仅影响 脚本本身的执行时间。在以下活动上花费的任何时间 发生在脚本执行之外,例如使用 不包括系统()、流操作、数据库查询等 确定脚本运行的最长时间时。 在测量时间是真实的Windows上,情况并非如此。 引自 http://php.net/manual/en/function.set-time-limit.php

您可以通过运行

<?php 
unlink('cocorico.txt'); 
while(true){ 
    file_put_contents('cocorico.txt', microtime(true).PHP_EOL, FILE_APPEND); 
} 

它会在 30 秒后停止(无论您是否关闭浏览器)您可以通过echo ini_get('max_execution_time');获得默认执行时间,并且可以像set_time_limit(3);一样设置标记为已接受的答案仅在ignore_user_abort上是正确的,但不要惊慌,如果您不将最大执行时间设置为 0 - 无限,您的"失败"脚本将永远运行;

根据我对这些东西如何工作的一点了解。从HTTP协议的角度来看,我会说是的,脚本将继续运行,因为浏览器只是向服务器发送请求页面,然后服务器开始执行脚本,并且不会从浏览器发送或接收信息,直到脚本完成加载和生成html输出, 就在这时,服务器将结果输出发送到浏览器并完成了工作。

看,浏览器无法"告诉"服务器用户不再通过HTTP协议查看页面。但是,HTTP 协议通过流套接字在 TCP 连接上运行,TCP 连接保持活动状态,直到其中一端选择中止连接(或达到一定的超时),现在我真的不知道浏览器如何处理这个问题。浏览器可以只打开一个连接,发送一个请求并关闭连接,然后服务器等待脚本并在另一个连接上发送响应。或者浏览器可以打开一个连接,保持此连接处于活动状态,直到服务器在同一连接上响应。如果事情以这种方式工作,那么服务器将真正有办法通过检查连接是否仍然处于活动状态或已被客户端关闭来了解用户是否不再查看页面。所以那将是一个不。

不知道太多关于这一点。