фоновое выполнение php скрипта

Фоновое выполнение скрипта на PHP без crontab

Озадачили меня тут написать демона на PHP. Т.е. скрипт, который будет заданное количество раз в заданное количество часов в случайное время (всегда случайное) выполнять определенные действия, и все это без использования cron’a.

До этого никогда не заморачивался, а тут после постановки задачи, начал было думать что так нельзя, что php скрипт надо вызывать браузером…ну задача то поставлена, надо выполнять.

Первая мысль — отключить ограничение времени выполнения скрипта. Запрещено хостером.

Вторая мысль — яваскриптом повторять аякс-запрос периодически (да хоть раз в секунду). — нельзя (требование заказчика).

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

1. Пачка сигарет, ночь, гугл, доки, книги, мануалы….
goto 1…

На выходе получаю:
Задача_1:
Реализовать генератор времен выполнения скрипта, исходя из заданных количества раз и количества часов. Хранить где-то эти времена.

Задача_2:
Работать после закрытия браузера

Задача_3:
Не вылетать после окончания ограничения времени выполнения скрипта

Задача_4:
Выполнять в нужное время какие-то действия.

Итак…
Пишем в конфиге исходные данные:

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

Далее сгенерируем и запишем в сессию массив времен запуска. Предварительно отсортируем массив по возрастанию, чтобы сначала шло раннее время (машину времени я еще не успел создать).

Теперь надо заставить скрипт работать, не обращая внимания на максимальное время выполнения, установленное сервером.
Принцип таков:
1) Определяем время начала работы скрипта;
2) Определяем установленное ограничение на время выполнения.
3) Запускаем цикл, внутри которого считаем текущее время и вычисляем общее время работы скрипта, сверяем текущее время со значениями в массиве времен запуска, и если совпадение есть, выполняем заданные действия (у меня они в файле exec.php). Для запуска файлов используем сокеты.
4) Повторяем цикл пока время работы скрипта не приблизится к максимально разрешенному. Я поставил — пока до максимального времени не останется 5 секунд.

Итак… считаем начальные данные по времени:

Собственно, цикл. Комментарии в коде.

Ну и, если разрешенное время подходит к концу, то завершаем цикл и благополучно запускаем этот же скрипт другие процессом (в 5 секунд точно уложимся)

Собственно, готово.
Далее у меня много заморочек было в выполнении тех самых действий — там надо было робота написать для поиска ссылок по заданным ссылкам.

Когда дописал все, озадачился полезным применением…Использовать его можно как службу. Он может следить за чем-то в сети и уведомлять Вас, например, по почте. И не надо никаких cron’ов.

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

Источник

PHP: запуск задачи в фоне

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

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

фоновое выполнение php скрипта

По-моему, в вашем случае самым простым вариантом будет exec:

К сожалению это будет работать только в *nix, потому что в Windows запустить процесс в фоне не так то просто

фоновое выполнение php скрипта

фоновое выполнение php скрипта

PHP CLI в фоне ведет себя плохо. Из того, что применяется «на скорую руку», хорошо себя ведут BASH, Perl и Python.

В задаче, где надо было беречь ресурсы, поступил так:
1. Скрипт на PHP сохраняет «задание» на BASH в некоторую директорию job
2. Крон ежеминутно запускает некий скрипт dispatcher, написанный на Perl (был жизнеспособный вариант и на BASH) который ищет N самых старых (по last modified time) скриптов из директории job, и запускает их.
3. Запускаемые скрипты первым делом уничтожают (rm) себя, чтобы не Они все равно выполнятся — ведь они уже загружены в ОЗУ. Результаты работы сохраняются в ФС или в БД, для обслуживания логики интерфейса

Число N для каждого конкретного сервера выявляется индивидуально — тестированием.

Был «подводный камень», который по первому разу даже был обнаружен совершенно невовремя — все, что запускает крон, должно работать с абсолютными путями.

Таким образом были сделаны проект вроде ютуба и аналогичный, тоже конвертирующий видео.

Источник

Фоновое выполнение php скрипта

фоновое выполнение php скрипта фоновое выполнение php скрипта фоновое выполнение php скрипта

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

В данном посте расскажу, как можно запускать фоновое выполнение PHP скриптов. Следует отметить, что без использования VPS (Virtual Private Server), то есть на обычном шаред хостинге, такой способ не сработает. Строго говоря, диспетчер создавался под Linux, хотя не исключена корректная работа и на FreeBSD. Даже скорее всего будет работать тоже.

В самом диспетчере ничего сложного нет, он скорее имеет больше заморочек по администрированию. Давайте сначала разберем, из чего он состоит со стороны ОС, какие используются команды:

Здесь мы запрашиваем список процессов с именем php. Остальные параметры влияют на отображение результатов, т.е. мы хотим видеть pid, и непосредственно полную команду, включая параметры. Пример вывода этой команды:

12769 php /path/to/1.php /path/to/price.xlsx

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

Это все, теперь сам код диспетчера и пример использования:

Допустим у нас есть php скрипт, который принимает в параметрах путь до файла, читает его и складывает содержимое в другой файл. Причем делает это очень долго (заменим на sleep 😉 )

А вот, как запускать его в фоновом режиме:

Метод launch может принимать 3 параметра. Первый это путь к файлу-скрипту со всеми параметрами; второй – максимальное время выполнения (по умолчанию 300 секунд) и третий разрешено ли запускать копии, то есть точно такие же процессы с идентичными параметрами.

Источник

Выполнение задачи в фоне (php)

Стоит такая задача:

Вот пример скрипта консольного (файл test.php):

Когда клиент посылает запрос, мы его обрабатываем:

Здесь мы просто выполняем наш тестовый скрипт и все.

Запрос приходит аяксом. Скрипт запускается, все хорошо, отрабатывает. Кнопка снова активируется.

Проблема:

Как это можно исправить?

4 ответа 4

Думаю, с таким подходом — никак. Потому что этот скрипт занимает весь Thread.

Есть вариант запускать exec(«/path/to/file/test.php &»); но не так, а так: exec(«/usr/bin/php /var/www/path/to/file/test.php &»); и не спать, а переложить выполнение на этот второй процесс. А если нужны данные ответа твоего «/path/to/file/test.php», то брать их из sdtout или в самом скрипте «test.php» записать вывод в файл — его наличие как-раз оповестит о том, что скрипт выполнился.

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

А то что написано у тебя, работать по твоей логике не будет.

//UPD комменты жгут как обычно. Их нехватает.

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

А так, нажал юзер на кнопку и забыл про её существование, когда дело дойдет до него он получит свой ответ и его данные будут обработаны.

Если ты не можешь выбрать из предложенных вариантов ни одного, тогда тут мало кто тебе чем поможет, можешь пойти изобрести велосипед :). Я дальше, честно не знаю чем тебе помочь. Ты настаиваешь на каком-то своем решении вопроса, не вчитываясь в ответы других.

Источник

PHP выполнить фоновый процесс

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

Любые предложения будут высоко ценится.

Предполагая, что это работает на машине Linux, я всегда обрабатывал это так:

Это позволяет вам легко отслеживать, что делает процесс и работает ли он до сих пор.

Напишите процесс как серверный скрипт на любом удобном для вас языке (php / bash / perl / etc) и затем вызовите его из функций управления процессом в вашем php-скрипте.

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

Я быстро проверил это из командной строки, используя «sleep 25s» в качестве команды, и это сработало как шарм.

Вы можете попытаться добавить это к вашей команде

Я просто хотел бы добавить очень простой пример для тестирования этой функциональности в Windows:

Создайте следующие два файла и сохраните их в веб-каталоге:

Дайте IUSR разрешение на запись в каталог, в котором вы создали вышеуказанные файлы

Разрешите IUSR ПРОЧИТАТЬ и ВЫПОЛНИТЬ C: \ Windows \ System32 \ cmd.exe

Хит foreground.php из веб-браузера

Следующее должно быть отображено в браузере с текущими временными метками и локальным ресурсом # в выходном массиве:

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

Вы должны увидеть testprocesses.php в том же каталоге, в котором были сохранены вышеуказанные файлы, и он должен содержать следующий текст с текущими временными метками:

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

Вот пример для Windows, использующий wget из пакетов gnuwin32.

Вы должны использовать popen / pclose для правильной работы.

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

Примечание 2: Пустые двойные кавычки после start «» обязательны, если команда является путем в кавычках. start Команда интерпретирует первый цитируемый параметр как заголовок окна.

Ну, я нашел немного быстрее и проще в использовании версию

Можете ли вы организовать отдельный процесс, а затем запустить свою копию в фоновом режиме? Я давно не занимался PHP, но функция pcntl-fork выглядит многообещающе.

Используйте эту функцию для запуска вашей программы в фоновом режиме. Он кроссплатформенный и полностью настраиваемый.

Примечание для пользователей Windows:
Вы не можете перенаправить stdout / stderr nul следующим образом:

Тем не менее, вы можете сделать это:

Примечания для пользователей * nix:

1) Используйте команду оболочки exec, если вы хотите получить фактический PID:

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

Вместо того, чтобы инициировать фоновый процесс, как насчет создания файла триггера и того, чтобы планировщик типа cron или autosys периодически выполнял скрипт, который ищет и воздействует на файлы триггера? Триггеры могут содержать инструкции или даже необработанные команды (еще лучше, просто сделайте это сценарием оболочки).

Если вы используете PHP, есть гораздо более простой способ сделать это с помощью pcntl_fork:

Я сильно использую fast_cgi_finish_request()

В сочетании с замыканием и register_shutdown_function ()

Затем зарегистрируйте это закрытие, которое будет выполнено перед выключением.

Наконец, когда ответ был отправлен клиенту, вы можете закрыть соединение с клиентом и продолжить работу с процессом PHP:

Закрытие будет выполнено после fast_cgi_finish_request.

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

Я тоже боролся с тем, чтобы заставить программу работать в фоновом режиме в Windows, пока скрипт продолжает выполняться. Этот метод, в отличие от других решений, позволяет запускать любую программу в свернутом, развернутом виде или без окна вообще. Решение llbra @ phpbrasil работает, но иногда оно создает нежелательное окно на рабочем столе, когда вы действительно хотите, чтобы задача выполнялась скрытой.

запуск Notepad.exe сворачивается в фоновом режиме:

запустить команду оболочки, невидимую в фоновом режиме:

Запустите MSPaint в развернутом виде и подождите, пока вы закроете его, прежде чем продолжить скрипт:

Источник

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *