PHP脚本可以启动另一个PHP脚本并退出吗?

时间:2009-09-19 05:15:28

标签: php http scripting asynchronous webserver

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

此外,第二个脚本是否有任何方法可以在PHP脚本到达特定行时通知它?

6 个答案:

答案 0 :(得分:7)

这是怎么做的。您告诉浏览器读取输出的前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');
?>

答案 1 :(得分:3)

您可以通过forking然后调用includerequire来有效实现此目的。

parent.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 parent.php
Sleeper started at 01:22:02
Parent waiting at 01:22:02
Sleeper done at 01:22:05
Parent done at 01:22:05

然而,分叉本身并不允许任何进程间通信,因此您必须找到一些其他方式通知父母该孩子已经到达特定行,就像您在问题中提到的那样。

答案 2 :(得分:1)

这是黑暗中的一个镜头:您可以尝试使用php的操作系统执行功能&

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.

答案 3 :(得分:1)

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

答案 4 :(得分:0)

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

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

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

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

要使浏览器完全加载(停止加载进度指示器),您可以使用MilanBabuš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

?>

答案 5 :(得分:0)

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

检查http://drupal.org/project/httprl中的代码(可以执行此操作)(非阻止请求)。我打算把这个lib推到github,一旦我把它更加精致;可以在drupal之外运行的东西。这应该是你想要的。