Может ли скрипт PHP запустить другой скрипт PHP и выйти? - PullRequest
6 голосов
/ 19 сентября 2009

Как PHP-скрипт может запустить другой PHP-скрипт и затем завершиться, оставив другой скрипт запущенным?

Кроме того, есть ли способ, чтобы 2-й скрипт сообщал PHP-скрипту, когда он достигает определенной строки?

Ответы [ 6 ]

7 голосов
/ 19 сентября 2009

Вот как это сделать. Вы просите браузер прочитать первые 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');
?>
3 голосов
/ 19 сентября 2009

Вы можете эффективно добиться этого, разветвив и затем позвонив include или require.

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

Однако разветвление по своей сути не допускает какого-либо межпроцессного взаимодействия, поэтому вам нужно найти какой-то другой способ сообщить родителю, что ребенок достиг определенной линии, как вы задали в вопросе.

1 голос
/ 19 сентября 2009

Будет ли pcntl_fork() делать что-то похожее на то, что вы в конечном итоге пытаетесь достичь? http://www.php.net/manual/en/function.pcntl-fork.php

1 голос
/ 19 сентября 2009

Вот снимок в темноте: вы можете попробовать использовать функции запуска ОС php с &.

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

Кроме того, если это не сработает, вы можете попробовать

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

Редактировать: nohup - это команда POSIX, которая игнорирует сигнал HUP (зависание), позволяя команде продолжать работать после выхода пользователя, который выполнил команду. Сигнал HUP (зависания) является обычным способом, которым терминал предупреждает в зависимости от процессов выхода из системы.

0 голосов
/ 22 февраля 2012

Вы можете создать запрос и закрыть соединение сразу после того, как оно будет записано.

Извлечь код в http://drupal.org/project/httprl, как это можно сделать (неблокирующий запрос). Я планирую перенести эту библиотеку на github, как только я получу ее более совершенной; что-то, что можно запустить за пределами друпала. Это должно сделать то, что вы ищете.

0 голосов
/ 19 сентября 2009

Если вы не хотите создавать расширение pcntl, хорошей альтернативой является использование proc_open ().

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

Используйте это вместе с stream_select (), чтобы ваш процесс PHP мог спать, пока что-то не произойдет с дочерним процессом, который вы создали.

Это эффективно создаст процесс в фоновом режиме, не блокируя родительский процесс PHP. Ваш PHP может читать и писать в STDIN, STDOUT, STDERR.

Чтобы завершить загрузку браузера (остановить индикатор прогресса загрузки), вы можете использовать то, что упомянул Милан Бабушков.

Ключ к тому, чтобы браузер думал, что 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

?>
...