我google的所有内容都告诉我这应该不正在发生,不过它是。
我正在构建一个迁移工具来构建一个主数据库'。我有一个管理面板,只有少数人可以访问。有一个合并按钮,启动AJAX调用以运行迁移php功能。考虑到我还在开发它,这个脚本花了多长时间我并不乐观。但是,一旦推到生产并填充生产数据库,我预计至少需要20分钟。我不需要关于最佳实践的讲座,告诉我不要通过GUI来完成。这也将成为一个cron,但是如果管理员愿意,我希望能够手动引导它。
所以这是我的过程。迁移功能立即关闭会话session_write_close()
,允许我同时运行多个PHP脚本。我这样做是因为我启动了一个setInterval来检查会话变量。这是我的进步'这只是我在循环迭代中的一个int。在我的迁移脚本中,我打开会话,向该int添加1,然后再次关闭会话。我在每个循环结束时这样做。
通过这样做,我已成功为我的AJAX创建了一个进度。现在我发现了一些东西如果我开始迁移,请关闭我的标签 - 或刷新。一旦我重新加载页面,我的进度就会继续增长。这告诉我迁移脚本仍然在后台执行。
如果我从浏览器中关闭100%,或清除我的会话,我就不再看到进度了。然而,这并不是因为脚本停止了。这是因为我的进度指示依赖于会话,一旦我清除会话或关闭浏览器,我的会话cookie就会发生变化。但是我知道脚本仍在运行,因为我可以手动查询数据库并查看正在添加的条目。
现在我的问题: 我不想要这个。如果我的浏览器关闭,如果我按下刷新,如果我断开连接等,我希望脚本被终止。我希望它能阻止中间过程。
我试过ignore_user_abort(false);但我非常确定这是特定于命令行的,对我没有任何影响。
我希望它能够被终止,因为我正在建立一个进步简历'功能,我们可以选择再次恢复迁移进度的位置。
有什么建议吗?
更新:
我不想走这条路,但我只是解决了一些问题,我可以有另一个会话变量。而且,我的上一次客户端已经过验证'这可能是一个时间戳。在我的javascript中,在客户端,每次30秒,我都可以点击PHP脚本,以便在上次验证客户端时更新'。在我在每个循环开始时的迁移功能中,我可以检查以确保时间戳不像60秒那样。如果它是60秒或更早,我做死了因此停止我的脚本。如果没有客户更新此时间戳,则本地意味着我们可以假设用户已关闭其浏览器/选项卡/刷新'。至于函数,我可以在命令行(cron)中忽略此检查。不是理想的解决方案,但这是我的计划B
答案 0 :(得分:1)
我是,并且确实使用了解决方案来ping客户端以指示客户端是否还活着。
基本上这就是我所做的:
从客户端,在javascript中,我设置了一个setInterval,每1.5秒运行一次,并通过AJAX命中php脚本。这个php脚本使用当前时间戳更新会话变量(如果需要,这可以很容易地成为数据库值,但是我不想要另一个查询的开销)。
$_SESSION['migration_listsync_clientLastPing_'.$decodedJson['progressKey']] = time();
然后,在我的迁移功能中,我会检查一下'时间戳'超过10秒钟,如果是我死了 - 从而杀死剧本。
if(isset($_SESSION['migration_listsync_clientLastPing_'.$progressKey])){
$calc = time() - $_SESSION['migration_listsync_clientLastPing_'.$progressKey];
if($calc > 10){
die();
}
}
我添加了一个' progressKey' param是调用函数时生成的1-100的随机数。这个数字是在javascript中生成的,并传递给我的两个AJAX调用。这样,如果用户刷新页面然后立即再次按下按钮,我们就不会有2个函数运行实例。老了'实例将在几秒钟后死亡,新实例将接管。
这不是一个理想的解决方案,但它是一个有效的解决方案。