Как запустить PHP-скрипт в фоновом режиме после отправки формы? - PullRequest
96 голосов
/ 07 января 2011

Проблема
У меня есть форма, которая при отправке запускает базовый код для обработки отправленной информации и вставляет ее в базу данных для отображения на веб-сайте уведомлений.Кроме того, у меня есть список людей, которые подписались на получение этих уведомлений по электронной почте и SMS.Этот список на данный момент тривиален (всего около 150), однако этого достаточно, чтобы циклически просмотреть всю таблицу подписчиков и отослать более 150 электронных писем.(Электронные письма отправляются индивидуально в соответствии с запросами системных администраторов нашего почтового сервера из-за массовых почтовых политик.)

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

  1. Во-первых, автор может подумать, что сервер отстает, и снова нажмите кнопку "Отправить"., в результате чего скрипт запускается заново или запускается дважды.Я мог бы решить эту проблему с помощью JavaScript, чтобы отключить кнопку и заменить текст, чтобы сказать что-то вроде «Обработка ...», однако это далеко не идеально, потому что пользователь все равно будет застревать на странице во время выполнения скрипта.(Кроме того, если JavaScript отключен, эта проблема по-прежнему существует.)

  2. Во-вторых, автор может преждевременно закрыть вкладку или браузер после отправки формы.Сценарий будет продолжать работать на сервере до тех пор, пока он не попытается выполнить обратную запись в браузер, однако, если пользователь затем просматривает любую страницу в нашем домене (пока сценарий еще выполняется), браузер зависает, загружая страницу, пока сценарий не завершится,(Это происходит только тогда, когда вкладка или окно браузера закрыты, а не все приложение браузера.) Тем не менее, это не идеально.

(возможно) Решение
Я решил, что хочу разбить часть скрипта на «электронную почту» на отдельный файл, который я могу вызвать после публикации уведомления.Первоначально я думал поместить это на страницу подтверждения после того, как уведомление было успешно опубликовано.Тем не менее, пользователь не будет знать, что этот скрипт запущен, и любые аномалии не будут им очевидны;Этот сценарий не может завершиться сбоем.

Но что, если я могу запустить этот сценарий в качестве фонового процесса?Итак, мой вопрос заключается в следующем: как я могу выполнить сценарий PHP для запуска в качестве фоновой службы и работать полностью независимо от того, что пользователь сделал на уровне формы?

РЕДАКТИРОВАТЬ: Это нельзя быть cron'ed.Он должен запускаться сразу после отправки формы.Это высокоприоритетные уведомления.Кроме того, системные администраторы, работающие на наших серверах, запрещают запускать кроны чаще, чем 5 минут.

Ответы [ 15 ]

2 голосов
/ 19 декабря 2016

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

     <?php

    post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue");
    //post_async("http://localhost/projectname/testpage.php", "Keywordname=testValue2");
    //post_async("http://localhost/projectname/otherpage.php", "Keywordname=anyValue");
    //call as many as pages you like all pages will run at once //independently without waiting for each page response as asynchronous.

  //your form db insertion or other code goes here do what ever you want //above code will work as background job this line will direct hit before //above lines response     
                ?>
                <?php

                /*
                 * Executes a PHP page asynchronously so the current page does not have to wait for it to     finish running.
                 *  
                 */
                function post_async($url,$params)
                {

                    $post_string = $params;

                    $parts=parse_url($url);

                    $fp = fsockopen($parts['host'],
                        isset($parts['port'])?$parts['port']:80,
                        $errno, $errstr, 30);

                    $out = "GET ".$parts['path']."?$post_string"." HTTP/1.1\r\n";//you can use POST instead of GET if you like
                    $out.= "Host: ".$parts['host']."\r\n";
                    $out.= "Content-Type: application/x-www-form-urlencoded\r\n";
                    $out.= "Content-Length: ".strlen($post_string)."\r\n";
                    $out.= "Connection: Close\r\n\r\n";
                    fwrite($fp, $out);
                    fclose($fp);
                }
                ?>

testpage.php

    <?
    echo $_REQUEST["Keywordname"];//case1 Output > testValue
//here do your background operations it will not halt main page
    ?>

PS: если вы хотите отправить параметры URL в виде цикла, выполните следующий ответ: https://stackoverflow.com/a/41225209/6295712

2 голосов
/ 09 мая 2014

Если вы работаете в Windows, исследуйте proc_open или popen ...

Но если мы на одном сервере "Linux" с cpanel, тогда это правильный подход:

#!/usr/bin/php 
<?php
$pid = shell_exec("nohup nice php -f            
'path/to/your/script.php' /dev/null 2>&1 & echo $!");
While(exec("ps $pid"))
{ //you can also have a streamer here like fprintf,        
 // or fgets
}
?>

Не используйте fork() или curl, если вы сомневаетесь, что справитесь с ними, это все равно что злоупотреблять вашим сервером

Наконец, в файле script.php, который вызывается вышеОбратите внимание, что вы написали:

<?php
ignore_user_abort(TRUE);
set_time_limit(0);
ob_start();
// <-- really optional but this is pure php

//Code to be tested on background

ob_flush(); flush(); 
//this two do the output process if you need some.        
//then to make all the logic possible


str_repeat(" ",1500); 
//.for progress bars or loading images

sleep(2); //standard limit

?>
2 голосов
/ 07 января 2011

Если вы работаете на платформе * nix, используйте cron и исполняемый файл php.

EDIT:

Существует довольно много вопросов, требующих "запуска php без cron" на SO. Вот один из них:

Планирование сценариев без использования CRON

Тем не менее, ответ exec () выше звучит очень многообещающе:)

0 голосов
/ 25 августа 2018

Это работает для меня.ты это

exec(“php asyn.php”.” > /dev/null 2>/dev/null &“);
0 голосов
/ 23 июня 2015

В моем случае у меня есть 3 параметра, одним из которых является строка (mensaje):

exec("C:\wamp\bin\php\php5.5.12\php.exe C:/test/N/trunk/api/v1/Process.php $idTest2 $idTest3 \"$mensaje\" >> c:/log.log &");

В моем Process.php у меня есть этот код:

if (!isset($argv[1]) || !isset($argv[2]) || !isset($argv[3]))
{   
    die("Error.");
} 

$idCurso = $argv[1];
$idDestino = $argv[2];
$mensaje = $argv[3];
...