【问题标题】:ignore_user_abort and redirect in php?ignore_user_abort 并在 php 中重定向?
【发布时间】:2010-12-26 03:20:00
【问题描述】:

我的设置与这里的人非常相似:
PHP Background Processes
即一个非常长的脚本,最多需要 10 分钟。但是,我需要在脚本运行时将调用脚本的人重定向回主页。换句话说,我需要这样的用户体验:

  • 点击更新按钮
  • 脚本开始执行,最多可能需要 10 分钟
  • 用户立即被重定向回主页

这可能只使用 PHP 吗?我知道我需要

ignore_user_abort(true); 
set_time_limit(0);

但是如何重定向用户?我不能使用 javascript,因为输出只会以长增量写入页面,并且我希望重定向是即时的。我可以使用标题吗?还是会惹上麻烦?

或者,我可以使用 cron 作业方法,但我在制作 cron 作业或让它运行 php 代码方面的经验为零(这甚至可能吗?)

谢谢,
马拉

更新:
使用标头重定向不起作用 - 在脚本完成之前页面不会加载。然而,最终网络服务器超时并显示“零大小回复:无法检索请求的 URL”(尽管脚本继续运行)。我想我唯一的选择是采用 cron 工作理念。咳!

【问题讨论】:

  • 在您提供的链接中,有一些使用 exec() 的建议。你试过吗?

标签: php process background


【解决方案1】:

我在处理登录时遇到了类似的情况。 为了保持简短... 我得到一个 PDT、IPN,每个都给我发一封日志记录电子邮件。 在 IPN VERIFIED 上向客户发送一封电子邮件,以向客户提供序列号和密码。 作为 PDT 和 IPN,我使用 goto 向我发送一封日志邮件,而不是一堆连续的 if。 在阅读了许多答案后,我研究了每一个答案,以找出适合我的问题的答案。 我终于用了……

<?php
  ignore_user_abort(TRUE); // at very top

当我通过渐进式检查(无 if)时,如果它们失败,我会使用例如...

  $mcalmsg .= "Check [serialnbr]\r\n";
  if (empty($_POST['serialnbr']))
    {    header('Location: '.$returnurl.'?error=1');
      $mcalmsg .= "Missing [serialnbr]\r\n";
      goto mcal_email; // Last process at end of script        
    }
    else
    {$serialnbr=strtoupper(htmlspecialchars(trim($_POST['serialnbr'])));
     $mcalmsg .= "[serialnbr]=$serialnbr\r\n";
    }

这(到目前为止)正在按需要工作。 当然,脚本中还有更多内容,但遵循相同的概念。 在这表示位置的地方,还有 3 个信息页面,每个页面都可以使用相同的概念显示。

mcal_email: //last process before ending, always gets here after all else from goto or clearing all checks.
 // compose email and send
?> // end of script

【讨论】:

    【解决方案2】:

    对我来说最明显的解决方案是将重定向和后台计算拆分为两个单独的文件,并让重定向脚本执行 10 分钟脚本:

    job.php:

    <?php
    // do the nasty calculation here
    

    redirect.php:

    <?php
    // start the script and redirect output of the script to nirvana, so that it
    // runs in the background
    exec ('php /path/to/your/script/job.php >> /dev/null 2>&1 &'); 
    
    // now the redirect
    header ('Location /index.php');
    

    对此工作的假设:您应该在禁用safe_mode 或已适当设置safe_mode_exec_dir 的Linux 主机上。当你在windows下运行时,需要修改exec字符串,而其余关于safe_mode的内容保持true。

    注意:当您需要向脚本传递参数时,请在传递之前使用escapeshellarg(),另请参阅PHP manual on exec

    【讨论】:

      【解决方案3】:

      我尝试了几种方法,但似乎都没有,我什至尝试使用register_shutdown_function(),但也失败了。我猜你一直在做一个 cron 工作。

      我只是想起了一些事情(但我没有测试过),你可以尝试做这样的事情:

      set_time_limit(0);
      ignore_user_abort(true);
      
      ob_start(); // not sure if this is needed
      
      // meta refresh or javascript redirect
      
      ob_flush(); // not sure if this is needed
      flush();
      
      // code to process here
      
      exit();
      

      不确定它是否会起作用,但您可以尝试一下。

      【讨论】:

      • 谢谢。如果可能的话,我想避免“软”重定向,所以我想我要去做一个 cron 工作!你建议怎么做?让 cron 作业运行“脚本管理器”类型的脚本,还是直接运行糟糕的更新脚本?
      • 我不确定我是否完全理解你,但在你进入 CRON 工作之前,我认为你应该尝试 Cassy 的解决方案,因为这两种方法的使用需要相同的要求。
      • 另外,您是否考虑过 AJAX 作为一种选择?用户点击某些东西,在后台处理一个 PHP 页面,完成后您可以在网页上显示“工作完成”消息。
      • ignore_user_abort 仅适用于从 cli 调用的脚本。我通过称为脚本的浏览器进行了尝试,但浏览器超时阻止了它们。
      • @inf3rno:我在非 CLI 环境中使用过 ignore_user_abort,虽然它没有“响应式”那么近,但它可以工作。
      【解决方案4】:

      为什么不试试标题方法,看看会发生什么?您还可以尝试调用 php 标头方法,看看这是否有效。我会反复试验,看看什么能解决你的问题。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2019-06-21
        • 1970-01-01
        • 2021-01-26
        • 1970-01-01
        • 2013-02-13
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多