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

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

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

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

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

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

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

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

 Andre Garcia17 янв. 2017 г., 21:15
Я видел, что вы уже придумали решение. я используюgearman с php для решения фоновых задач. Это идеально подходит для масштабирования, если вы столкнулись с большой обработкой и большими нагрузками. Вы должны взглянуть на это.
 Simon07 янв. 2011 г., 16:10
Вы хотите запускать его регулярно (каждый день или каждый час) или при отправке? Я думаю, вы могли бы использовать PHPexec() но я никогда не пробовал это.
 Evan Mulawski07 янв. 2011 г., 16:09
Запустите задание cron и предупредите пользователя на другой странице, что его запрос обрабатывается или что-то в этом роде.
 Joshy Francis07 окт. 2017 г., 08:22
Следуйте этому ответу на [stackoverflow] (stackoverflow.com/a/46617107/6417678)
 KeepMove16 дек. 2013 г., 16:55
Я просто используюajax и вставкаsleep() с интервалом времени внутри цикла (я использую foreach в моем случае) для запуска фонового процесса. Это прекрасно работает на моем сервере. Не уверен насчет других. Я тоже добавляюignore_user_abort() а такжеset_time_limit() (с расчетным временем окончания) перед циклом, чтобы убедиться, что сценарий не будет остановлен сервером, который я использую, даже в соответствии с моим тестом сценарий, выполняющий задачу безignore_user_abort() а такжеset_time_limit().

Ответы на вопрос(15)

exec("php script.php") может это сделать.

ИзРуководство по эксплуатации:

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

Поэтому, если вы перенаправите вывод в файл журнала (что в любом случае является хорошей идеей), ваш вызывающий скрипт не будет зависать, и ваш почтовый скрипт будет работать в bg.

 Michael Irigoyen07 янв. 2011 г., 16:18
Спасибо, но это не сработало. Скрипт все еще «зависает», пока обрабатывает второй файл.
 Simon07 янв. 2011 г., 16:21
Посмотрите на похвалуphp.net/manual/en/function.exec.php#80582 Похоже, это потому, что Safe_mode включен. Существует обходной путь под Unix.
 Michael Irigoyen07 янв. 2011 г., 18:04
К сожалению, безопасный режим не включен на нашей установке. Странно, что оно все еще висит.

используяproc_open:

$descriptorspec = array(
   array('pipe', 'r'),               // stdin
   array('file', 'myfile.txt', 'a'), // stdout
   array('pipe', 'w'),               // stderr
);

$proc = proc_open('php email_script.php &', $descriptorspec, $pipes);

& быть важным битом здесь. Сценарий будет продолжен, даже если исходный сценарий завершился.

 naggarwal1125 дек. 2015 г., 12:23
@netcoder: что делать, если я не хочу сохранять результат в каком-либо файле. какие изменения требуются в stdout?
 Michael Irigoyen07 янв. 2011 г., 18:10
Это работает, когда я не звонюproc_close когда задача была выполнена.proc_close заставляет скрипт зависать примерно от 15 до 25 секунд. Мне нужно было бы вести журнал, используя информацию о канале, поэтому мне нужно открыть файл для записи, закрыть его, а затем закрыть соединение proc. Так что, к сожалению, это решение не работает для меня.
 netcoder07 янв. 2011 г., 18:19
Конечно ты не звонишьproc_close, в этом-то и дело! И да, вы можете передать в файл сproc_open, Смотрите обновленный ответ.

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

exec(“php asyn.php”.” > /dev/null 2>/dev/null &“);
 khalid J-A11 нояб. 2018 г., 03:20
Что делать, если у меня есть значения записей? из формы, и я отправляю его через ajax иserialize() функция. например у меня естьindex.php с формой, и я отправляю значение через ajax на index2.php Я хочу выполнить отправку данных в index2.php в фоновом режиме, что вы предлагаете? Спасибо

Вам понадобится ssh доступ к машине, чтобы запустить скрипт как cron.

$ php scriptname.php запустить его.

 Teson07 янв. 2011 г., 16:10
нет необходимости в SSH. Многие хосты запрещают ssh, но имеют поддержку cron.
 Michael Irigoyen07 янв. 2011 г., 16:12
Спасибо, но я обновил оригинальный вопрос. Кроны не вариант в этом случае.

cron иphp исполняемый файл.

РЕДАКТИРОВАТЬ:

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

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

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

 Michael Irigoyen07 янв. 2011 г., 16:11
Спасибо, но я обновил оригинальный вопрос. Кроны не вариант в этом случае.

http://php.net/manual/en/function.httprequest-send.php

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

свои собственные сценарии, вы можете создать простой сервер fifo, используя php (хотя вам придется перекомпилировать php с помощьюposix Поддержка дляfork).

Сервер действительно может быть написан на чем угодно, вы, вероятно, можете легко сделать это на python.

Или самое простое решение будет отправкаHttpRequest и не читает возвращаемые данные, но сервер может уничтожить скрипт до того, как он закончит обработку.

Пример сервера:

<?php
define('FIFO_PATH', '/home/user/input.queue');
define('FORK_COUNT', 10);

if(file_exists(FIFO_PATH)) {
    die(FIFO_PATH . ' exists, please delete it and try again.' . "\n");
}

if(!file_exists(FIFO_PATH) && !posix_mkfifo(FIFO_PATH, 0666)){
    die('Couldn\'t create the listening fifo.' . "\n");
}

$pids = array();
$fp = fopen(FIFO_PATH, 'r+');
for($i = 0; $i < FORK_COUNT; ++$i) {
    $pids[$i] = pcntl_fork();
    if(!$pids[$i]) {
        echo "process(" . posix_getpid() . ", id=$i)\n";
        while(true) {
            $line = chop(fgets($fp));
            if($line == 'quit' || $line === false) break;
            echo "processing (" . posix_getpid() . ", id=$i) :: $line\n";
        //  $data = json_decode($line);
        //  processData($data);
        }
        exit();
    }
}
fclose($fp);
foreach($pids as $pid){
    pcntl_waitpid($pid, $status);
}
unlink(FIFO_PATH);
?>

Пример клиента:

<?php
define('FIFO_PATH', '/home/user/input.queue');
if(!file_exists(FIFO_PATH)) {
    die(FIFO_PATH . ' doesn\'t exist, please make sure the fifo server is running.' . "\n");
}

function postToQueue($data) {
    $fp = fopen(FIFO_PATH, 'w+');
    stream_set_blocking($fp, false); //don't block
    $data = json_encode($data) . "\n";
    if(fwrite($fp, $data) != strlen($data)) {
        echo "Couldn't the server might be dead or there's a bug somewhere\n";
    }
    fclose($fp);
}
$i = 1000;
while(--$i) {
    postToQueue(array('xx'=>21, 'yy' => array(1,2,3)));
}
?>

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

form_action_page.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

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

?>
 i am ArbZ09 мая 2014 г., 22:18
Извините, что впоследствии отредактировал его, потому что я использую свой мобильный телефон, и на самом деле это намного сложнее, чем написание скрипта exec (). Лол ;)

fastcgi_finish_request Функция, которая при вызове сбрасывает все оставшиеся выходные данные в браузер и закрывает сеанс Fastcgi и HTTP-соединение, позволяя сценарию работать в фоновом режиме.

Пример:

<?php
header('Content-Type: application/json');
echo json_encode(['ok' => true]);
fastcgi_finish_request(); // The user is now disconnected from the script

// do stuff with received data,
 Aurangzeb16 окт. 2018 г., 08:51
это именно то, что я искал, в shell_exec мне нужно каким-то образом перенести опубликованные данные в исполняемый скрипт, что само по себе является трудоемкой задачей в моем случае, а также усложняет задачу.
 Danogentili28 янв. 2019 г., 00:52
Я предлагаю вам взглянуть на журналы, чтобы увидеть, что не так; если вы все еще не можете понять это, создайте новый квестон.
 ekashking20 янв. 2019 г., 20:23
Ничто не работает послеfastcgi_finish_request();

один из которых является строкой (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];

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

Этот второй PHP-скрипт должен быть запущен как cron.

 Michael Irigoyen07 янв. 2011 г., 16:11
Спасибо, но я обновил оригинальный вопрос. Кроны не вариант в этом случае.

Более простой способ запустить PHP-скрипт в фоновом режиме

php script.php >/dev/null &

Сценарий будет работать в фоновом режиме, и страница также быстрее достигнет страницы действий.

вы не можете сделать это простым способом (см. Fork exec и т. Д. (Не работают под окнами)), возможно, вы можете изменить подход, использовать фон браузера, публикующего форму в ajax, так что если сообщение все еще работа у вас нет времени ожидания.
Это может помочь, даже если вам придется долго заниматься.

При отправке почты всегда рекомендуется использовать спулер, это может быть локальный и быстрый smtp-сервер, который принимает ваши запросы и помещает их в реальный MTA или помещает все в БД, а не использует cron, который спулирует очередь.
Cron может находиться на другой машине, вызывая спулер как внешний URL:

* * * * * wget -O /dev/null http://www.example.com/spooler.php
Решение Вопроса

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

Я использую следующую строку для вызова сценария электронной почты:

shell_exec("/path/to/php /path/to/send_notifications.php '".$post_id."' 'alert' >> /path/to/alert_log/paging.log &");

Важно отметить& в конце команды (как указано @netcoder). Эта команда UNIX запускает процесс в фоновом режиме.

Дополнительные переменные, заключенные в одинарные кавычки после пути к сценарию, задаются как$_SERVER['argv'] переменные, которые я могу вызвать в моем сценарии.

Сценарий электронной почты затем выводится в мой файл журнала, используя>> и выведет что-то вроде этого:

[2011-01-07 11:01:26] Alert Notifications Sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 38.71 seconds)
[2011-01-07 11:01:34] CRITICAL ERROR: Alert Notifications NOT sent for http://alerts.illinoisstate.edu/2049 (SCRIPT: 23.12 seconds)
 Perocat27 апр. 2014 г., 15:31
Что это такое$post_id после пути сценария php?
 Liam Bailey12 янв. 2013 г., 16:05
Благодарю. Это спасло мою жизнь.
 Chique09 окт. 2014 г., 22:05
@Perocat - это переменная, которую вы отправляете в скрипт. В этом случае он отправляет идентификатор, который будет параметром вызываемого скрипта.
 Al.G.29 сент. 2017 г., 00:03
Есть ожидающее редактирование предложение о побеге$post_id; Я бы предпочел привести его непосредственно к числу:(int) $post_id, (Обращаю ваше внимание, чтобы решить, что лучше.)
 Tangocoder23 авг. 2012 г., 04:35
У меня это тоже получилось, спасибо

Ваш ответ на вопрос