Отказаться от длинных процессов в PHP (но пусть они завершатся) - PullRequest
4 голосов
/ 08 марта 2009

У меня есть HTML-форма, которая отправляется на страницу PHP, которая запускает скрипт. Выполнение сценария может занять от 3 до 30 секунд - пользователю не нужно находиться рядом, чтобы завершить выполнение этого сценария.

Можно ли запустить скрипт PHP, сразу же напечатать пользователю "спасибо" (или что-то еще) и позволить ему идти своим путем, пока ваш скрипт продолжает работать?

В моем конкретном случае я отправляю данные формы в скрипт php, который затем отправляет данные во многие другие места. Ожидание успеха всех постов в данный момент не в моих интересах. Я просто хотел бы запустить скрипт, позволить пользователю идти и делать все что угодно, и все.

Ответы [ 6 ]

2 голосов
/ 08 марта 2009

Поместите вашу долгосрочную работу в другой скрипт php, например

background.php:

sleep(10);
file_put_contents('foo.txt',mktime());

foreground.php

$unused_but_required = array();
proc_close(proc_open ("php background.php &", array(), $unused_but_required));
echo("Done);

Вы увидите «Готово» немедленно, а файл будет записан через 10 секунд.

Я думаю, что proc_close работает, потому что мы не предоставляем proc_open никаких каналов и дескрипторов файлов.

1 голос
/ 08 марта 2009

Вы можете использовать set_time_limit и ignore_user_abort, но, вообще говоря, я бы рекомендовал поместить задание в очередь и использовать асинхронный скрипт для его обработки. Это гораздо более простой и прочный дизайн.

1 голос
/ 08 марта 2009

В скрипте вы можете установить:

<?php
 ignore_user_abort(true);

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

 set_time_limit(0);

С тех пор сценарий может выполняться вечно.

0 голосов
/ 10 марта 2009

У меня получилось следующее.

<?php

  // Ignore User-Requests to Abort
  ignore_user_abort(true);
  // Maximum Execution Time In Seconds
  set_time_limit(30);

  header("Content-Length: 0");
  flush();

  /*

    Loooooooong process

  */

?>
0 голосов
/ 08 марта 2009

Theres API-оболочка вокруг pcntl_fork () с именем php_fork .

Но также этот вопрос был на Daily WTF ... не забивайте гвоздь стеклянной бутылкой.

0 голосов
/ 08 марта 2009

Вы можете попробовать функции flush и связанные с ними выходные буферы, чтобы немедленно отправить все содержимое буфера в браузер:

...