Проблема
У меня есть форма, которая при отправке запускает базовый код для обработки отправленной информации и вставки ее в базу данных для отображения на веб-сайте уведомлений. Кроме того, у меня есть список людей, которые подписались на получение этих уведомлений по электронной почте и SMS. На данный момент этот список тривиален (всего около 150), однако его достаточно, чтобы циклически перебрать всю таблицу подписчиков и отправить более 150 электронных писем. (Электронные письма отправляются индивидуально по запросу системных администраторов нашего почтового сервера из-за политики массовой рассылки.)
В это время человек, разместивший уведомление, будет сидеть на последней странице формы почти минуту без какого-либо положительного подтверждения того, что его уведомление публикуется. Это приводит к другим потенциальным проблемам, все из которых имеют возможные решения, которые я считаю не идеальными.
Во-первых, автор может подумать, что сервер отстает, и снова нажать кнопку «Отправить», в результате чего скрипт запустится заново или будет запущен дважды. Я мог бы решить эту проблему, используя JavaScript, чтобы отключить кнопку и заменить текст, чтобы сказать что-то вроде «Обработка ...», однако это далеко не идеально, потому что пользователь все равно будет застрять на странице на время выполнения скрипта. (Кроме того, если JavaScript отключен, эта проблема все еще существует.)
Во-вторых, автор может преждевременно закрыть вкладку или браузер после отправки формы. Сценарий будет продолжать работать на сервере до тех пор, пока он не попытается выполнить обратную запись в браузер, однако, если пользователь затем перейдет на любую страницу в нашем домене (пока скрипт все еще запущен), браузер зависнет при загрузке страницы, пока скрипт не завершится. . (Это происходит только тогда, когда закрывается вкладка или окно браузера, а не все приложение браузера.) Тем не менее, это далеко не идеально.
(Возможное) Решение.
Я решил, что хочу выделить часть сценария «электронная почта» в отдельный файл, который я могу вызвать после публикации уведомления. Первоначально я думал разместить это на странице подтверждения после того, как уведомление было успешно отправлено. Однако пользователь не узнает, что этот сценарий запущен, и ему не будут очевидны какие-либо аномалии; Этот сценарий не может потерпеть неудачу.
Но что, если я могу запустить этот сценарий в фоновом режиме? Итак, мой вопрос таков: как я могу выполнить скрипт PHP для запуска в качестве фоновой службы и полностью независимо от того, что пользователь сделал на уровне формы?
РЕДАКТИРОВАТЬ: это нельзя cron'ed. Он должен запускаться в момент отправки формы. Это уведомления с высоким приоритетом. Кроме того, системные администраторы, работающие на наших серверах, запрещают запускать crons чаще, чем 5 минут.
источник
exec()
но я никогда этого не пробовал.ajax
и вставляюsleep()
с интервалом времени внутри цикла (в моем случае я использую foreach) для запуска фонового процесса. Он отлично работает на моем сервере. Не уверен насчет других. Я также добавляюignore_user_abort()
иset_time_limit()
(с расчетным временем окончания) перед циклом, чтобы убедиться, что скрипт не будет остановлен сервером, который я использую, даже в соответствии с моим тестом, скрипт завершает задачу безignore_user_abort()
иset_time_limit()
.gearman
php для решения фоновых задач. Он идеально подходит для масштабирования, если вы столкнулись с большой обработкой и большими нагрузками. Вам стоит взглянуть на это.Ответы:
Делая некоторые эксперименты с
exec
иshell_exec
я обнаружил решение , которое работало отлично! Я предпочитаю использовать,shell_exec
чтобы я мог регистрировать каждый процесс уведомления, который происходит (или не происходит). (shell_exec
возвращается в виде строки, и это было проще, чем использоватьexec
, назначать вывод переменной и затем открывать файл для записи.)Я использую следующую строку для вызова сценария электронной почты:
Важно замечать
&
в конце команды (как отметил @netcoder). Эта команда UNIX запускает процесс в фоновом режиме.Дополнительные переменные, заключенные в одинарные кавычки после пути к сценарию, задаются как
$_SERVER['argv']
переменные, которые я могу вызывать в моем сценарии.Затем сценарий электронной почты выводит в мой файл журнала с помощью
>>
и выводит что-то вроде этого:источник
$post_id
после пути к php-скрипту?$post_id
; Я предпочел бы бросить его прямо на номер:(int) $post_id
. (Взывая к вашему вниманию, чтобы решить, что лучше.)На серверах Linux / Unix вы можете выполнять задание в фоновом режиме с помощью proc_open :
&
Является важным здесь немного. Скрипт будет продолжен, даже если исходный скрипт закончился.источник
proc_close
когда задача выполнена.proc_close
заставляет скрипт зависать от 15 до 25 секунд. Мне нужно будет вести журнал, используя информацию о канале, поэтому мне нужно открыть файл, в который нужно записать, закрыть его, а затем закрыть соединение proc. Так что, к сожалению, у меня это решение не работает.proc_close
, в том-то и дело! И да, вы можете подключиться к файлу с расширениемproc_open
. См. Обновленный ответ.Из всех ответов ни один не рассматривал до смешного простую функцию fastcgi_finish_request , которая при вызове сбрасывает весь оставшийся вывод в браузер и закрывает сессию Fastcgi и HTTP-соединение, позволяя скрипту работать в фоновом режиме.
Пример:
источник
PHP
exec("php script.php")
может это сделать.Из руководства :
Поэтому, если вы перенаправляете вывод в файл журнала (что в любом случае является хорошей идеей), ваш вызывающий скрипт не зависнет, а ваш почтовый скрипт будет работать в bg.
источник
А почему бы не сделать HTTP-запрос к скрипту и не проигнорировать ответ?
http://php.net/manual/en/function.httprequest-send.php
Если вы сделаете запрос в скрипте, который вам нужно вызвать, ваш веб-сервер запустит его в фоновом режиме, и вы можете (в своем основном скрипте) показать сообщение, сообщающее пользователю, что скрипт запущен.
источник
Как насчет этого?
Этот второй скрипт PHP должен быть настроен на запуск как cron.
источник
Насколько я знаю, вы не можете сделать это простым способом (см. Fork exec и т. Д. (Не работают под окнами)), возможно, вы можете отменить подход, использовать фон браузера, отправляющего форму в ajax, поэтому, если сообщение все еще работа у тебя нет времени ждать.
Это может помочь, даже если вам придется долго дорабатывать.
При отправке почты всегда предлагается использовать спулер, может быть локальный и быстрый сервер smtp, который принимает ваши запросы и передает их в реальный MTA или помещает все в БД, чем использовать cron, который буферизует очередь.
Cron может находиться на другом компьютере, вызывая диспетчер очереди печати как внешний URL:
источник
Фоновая работа cron - хорошая идея для этого.
Вам понадобится ssh-доступ к машине, чтобы запустить скрипт как cron.
$ php scriptname.php
запустить его.источник
Если вы можете получить доступ к серверу через ssh и запускать свои собственные сценарии, вы можете создать простой сервер fifo с использованием php (хотя вам придется перекомпилировать php с
posix
поддержкойfork
).Сервер действительно может быть написан на чем угодно, вы, вероятно, легко сможете сделать это на python.
Или самым простым решением было бы отправить HttpRequest и не читать возвращаемые данные, но сервер может уничтожить скрипт до того, как он завершит обработку.
Пример сервера:
Пример клиента:
источник
Более простой способ запустить PHP-скрипт в фоновом режиме -
Скрипт будет работать в фоновом режиме, и страница также быстрее достигнет страницы действия.
источник
Предполагая, что вы работаете на платформе * nix, используйте
cron
иphp
исполняемый файл.РЕДАКТИРОВАТЬ:
Уже есть ряд вопросов, касающихся «запуска php без cron» на SO. Вот один:
Планирование сценариев без использования CRON
Тем не менее, ответ exec () выше звучит очень многообещающе :)
источник
Если вы используете Windows, поищите
proc_open
илиpopen
...Но если мы находимся на одном сервере "Linux" с cpanel, то это правильный подход:
Не используйте
fork()
илиcurl
если вы сомневаетесь, что справитесь с ними, это похоже на злоупотребление вашим серверомНаконец,
script.php
обратите внимание на файл, который указан выше, убедитесь, что вы написали:источник
для фонового работника я думаю, вам следует попробовать этот метод, он поможет вызвать столько страниц, сколько вам нравится, все страницы будут запускаться одновременно независимо, не дожидаясь ответа каждой страницы как асинхронного.
form_action_page.php
testpage.php
PS: если вы хотите отправить параметры URL-адреса в виде цикла, следуйте этому ответу: https://stackoverflow.com/a/41225209/6295712
источник
В моем случае у меня есть 3 параметра, один из них - строка (mensaje):
В моем Process.php у меня есть этот код:
источник
Это работает для меня. тыр это
источник
serialize()
функцию. например, у меня естьindex.php
форма, и я отправляю значение через ajax в index2.php. Я хочу выполнить отправку данных в index2.php в фоновом режиме, что вы предлагаете? спасибоИспользуйте Amphp для параллельного и асинхронного выполнения заданий.
Установить библиотеку
Пример кода
Для вашего варианта использования вы можете сделать что-то вроде ниже
источник