【问题标题】:Can a PHP script start another PHP script and exit?PHP 脚本可以启动另一个 PHP 脚本并退出吗?
【发布时间】:2012-04-26 11:02:08
【问题描述】:

一个 PHP 脚本如何启动另一个 PHP 脚本,然后退出,让另一个脚本继续运行?

另外,当第二个脚本到达特定行时,有什么方法可以通知 PHP 脚本?

【问题讨论】:

  • 可以curl 帮忙吗?知道怎么做吗?
  • 卷曲?可能只有head 请求,但我持怀疑态度
  • - 如果第一个脚本终止,第二个脚本如何通知第一个? - 这是网页还是控制台脚本?
  • N/A - 请参阅下面米兰的回答。

标签: php http scripting asynchronous webserver


【解决方案1】:

这里是如何做到这一点。您告诉浏览器读取输出的前 N ​​个字符,然后关闭连接,同时您的脚本继续运行直到完成。

<?php
ob_end_clean();
header("Connection: close");
ignore_user_abort(); // optional
ob_start();
echo ('Text the user will see');
$size = ob_get_length();
header("Content-Length: $size");
ob_end_flush();     // Will not work
flush();            // Unless both are called !

// At this point, the browser has closed connection to the web server

// Do processing here
include('other_script.php');

echo('Text user will never see');
?>

【讨论】:

  • 你能解释一下你的代码吗?例如,刷新会诱使浏览器认为 HTTP 请求已经结束?
  • 是的,它有效!也请发布这个问题的答案——stackoverflow.com/questions/1436575/…
  • 此代码直接来自 php 手册。 php.net/manual/en/features.connection-handling.php#71172
  • 是的,GZipp,我知道。实际上,这段代码是在 2004 年左右写在某个邮件列表上的,直到现在我只是将它保存在一个 .txt 文件中。显然有人拿走了它并复制/粘贴到 PHP 手册的 cmets 部分。无论如何,我并没有声称它是我写的——只是说这是解决这个问题的方法。
  • 如果 PHP 执行时间有限,这是否也有效?即,如果执行时间结束,并且“生成”的 PHP 脚本仍在运行,它会继续运行吗? (我想它不会......)
【解决方案2】:

您可以通过forking 然后调用includerequire 来有效地实现这一点。

父.php:

<?php

    $pid = pcntl_fork();
    if ($pid == -1) {
        die("couldn't fork");
    } else if ($pid) { // parent script
        echo "Parent waiting at " . date("H:i:s") . "\n";
        pcntl_wait($status);
        echo "Parent done at " . date("H:i:s") . "\n";
    } else {
        // child script
        echo "Sleeper started at " . date("H:i:s") . "\n";
        include('sleeper.php');
        echo "Sleeper done at " . date("H:i:s") . "\n";
    }

?>

sleeper.php:

<?php
sleep(3);
?>  

输出:

$ php 父级.php 卧铺开始于 01:22:02 家长在 01:22:02 等候 01:22:05 完成的卧铺 家长在 01:22:05 完成

但是,分叉本质上不允许任何进程间通信,因此您必须找到其他方法来通知父母孩子已经到达特定线路,就像您在问题中提出的那样。

【讨论】:

【解决方案3】:

这是在黑暗中的一个镜头:你可以尝试使用 php 的操作系统执行函数和&amp;

exec("./somescript.php &");

另外,如果还不行,你可以试试

exec("nohup ./somescript.php &");

编辑:nohup is a POSIX command to ignore the HUP (hangup) signal, enabling the command to keep running after the user who issues the command has logged out. The HUP (hangup) signal is by convention the way a terminal warns depending processes of logout.

【讨论】:

    【解决方案4】:

    pcntl_fork() 会做与你最终想要完成的事情类似的事情吗? http://www.php.net/manual/en/function.pcntl-fork.php

    【讨论】:

      【解决方案5】:

      如果您不想构建 pcntl 扩展,那么一个不错的选择是使用 proc_open()。

      http://www.php.net/manual/en/function.proc-open.php

      将它与 stream_select() 一起使用,以便您的 PHP 进程可以休眠,直到您创建的子进程发生某些事情。

      这将有效地在后台创建一个进程,而不会阻塞父 PHP 进程。你的 PHP 可以读写 STDIN、STDOUT、STDERR。

      要使浏览器完成加载(停止加载进度指示器),您可以使用 Milan Babuškov 提到的内容。

      让浏览器认为 HTTP 请求完成的关键是向它发送内容长度。为此,您可以开始缓冲请求,然后在发送 Content-Length 标头后刷新它。

      例如:

      <?php
      
      ob_start();
      
      // render the HTML page and/or process stuff
      
      header('Content-Length: '.ob_get_length());
      ob_flush();
      flush();
      
      // can do more processing
      
      ?>
      

      【讨论】:

        【解决方案6】:

        您可以在写入完成后立即创建请求并关闭连接。

        签出http://drupal.org/project/httprl 中的代码,因为可以这样做(非阻塞请求)。一旦我得到更完善,我计划将这个库推送到 github;可以在drupal之外运行的东西。这应该可以满足您的需求。

        【讨论】:

          猜你喜欢
          • 2014-02-26
          • 2013-03-20
          • 1970-01-01
          • 2012-04-05
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2013-10-02
          相关资源
          最近更新 更多