关闭页面后脚本会继续运行吗?

IT技术 php javascript
2021-03-15 16:58:12

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

5个回答

见这里: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”标志. 所以,在我的理解中,没有办法中断不产生任何输出的代码。”

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

如果您阅读本文,也请查看下面的评论。

@Mörre:然后我添加ignore_user_abort(false);到我的 PHP 脚本的顶部并再次运行......相同的结果。请解释。
2021-04-18 16:58:12
感谢 ignore-user-abort 正是我正在寻找的
2021-04-21 16:58:12
@Mörre:总之。你在技术上是绝对正确的。但我实际上是正确的,对于现实生活中真正发生的事情。大多数情况下,在 PHP 脚本完全完成之前,不会向 PHP 脚本提供连接状态更新,此时它无关紧要,因为没有任何东西可以取消。
2021-04-23 16:58:12
@Mörre:好的。我很生气和沮丧,因为它违背了我所理解的一切。对不起:) 所以我不得不测试一下。现在请解释一下。我写了一个 PHP 脚本,每秒生成一个文件,持续 30 秒。我从我的浏览器 (IE) 运行脚本,然后在第五个 5 文件之后,我关闭了浏览器。该脚本继续在服务器上运行,直到生成所有 30 个文件。告诉我如何调和?这正是我认为会发生的事情,以及我在回答中所说的......(来自经验,我希望有点有value??)
2021-05-12 16:58:12
@Mörre:在我的...中ignore_user_abort设置为Off(false) phpinfo... 它在 PHP、ASP、ASP.Net、CGI 等所有内容中一直以这种方式工作。如果浏览器关闭,并且某些东西陷入无限循环,我必须重新启动 IIS。这叫做经验。此外,如果您是对的,那么为什么我们会遇到所有这些未关闭会话的问题,以及关于 SO 和其他有关确定用户是否关闭浏览器的问题?通常没有给出解决方案(除了捕获onbeforeunload并不总是有效的事件 - 那是客户端)。
2021-05-15 16:58:12

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

  • 有人杀死服务器
  • 服务器杀死 php 脚本

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

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

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

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

一旦用户中止,以下脚本将停止:

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() 过早地释放会话;

“此脚本将停止,因为 flush() 和 ob_flush() 将强制 PHP” - 这不是(必然)所以,请参阅我对这个问题的回答(而不是我的回答本身)的长尾评论。
2021-04-21 16:58:12

默认没有。请参阅连接处理文档,尤其是:

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

这是正确的,但是对于一个 caviet。PHP 不会知道断开连接,直到它尝试向客户端发送数据。因此,如果您在没有任何输出的情况下进行 30 分钟的预处理并在 1 分钟内杀死浏览器,则 30 分钟将完成。
2021-05-14 16:58:12

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

警告当 PHP 在安全模式下运行时,此功能无效。除了关闭安全模式或更改 php.ini 中的时间限制外,没有其他解决方法。 注意: set_time_limit() 函数和配置指令 max_execution_time 只影响脚本本身的执行时间。在确定脚本运行的最长时间时,不包括在脚本执行之外发生的活动(例如使用 system() 的系统调用、流操作、数据库查询等)上花费的任何时间。在测量时间是真实的 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 连接一直保持活动状态,直到其中一端选择中止连接(或达到某个超时),现在我真的不知道如何浏览器处理这个。浏览器可以只打开一个连接,发送请求并关闭连接,然后服务器等待脚本并在另一个连接上发送响应。或者浏览器可以打开一个连接,保持这个连接处于活动状态,直到服务器响应同一个连接。如果事情以这种方式工作,那么服务器真的有办法知道用户是否不再查看页面,只需检查连接是否仍然有效或已被客户端关闭。所以那将是一个不。

不知道是怎么回事。

所以......恢复整个事情......你什么都没添加并确认我的假设是正确的......现在睡一觉。
2021-04-24 16:58:12
(我删除了我的评论,我误解了答案)
2021-04-24 16:58:12
是的...酷...请告诉我更多。因为在我看来,你说的和我在上面的评论中说的一样。
2021-04-26 16:58:12
@Mörre:请参阅我对您的回答的评论。我做了几次测试,因为我不敢相信你,这一直是我的经验。请解释我发现的结果。
2021-04-29 16:58:12
不,我不认为,您是否阅读了我的所有答案?嘿,retoric question...我提到我不知道连接是否保持活动,我说如果它保持活动,那么答案是否定的。下次阅读时请多加注意。
2021-05-06 16:58:12