Запустите php скрипт как демон процесса
Мне нужно запустить PHP-скрипт в качестве демона процесса (ждать инструкций и делать вещи). хрон не будет делать это для меня потому, что меры должны быть приняты, как только инструкция прибывает. Я знаю, что PHP не самый лучший вариант для процессов демона из-за проблем с управлением памятью, но по разным причинам я должен использовать PHP в этом случае. Я наткнулся на инструмент libslack под названием Daemon (http://libslack.org/daemon) кажется, это помогает мне управлять процессами демона, но нет никаких обновлений за последние 5 лет, поэтому мне интересно, если вы знаете, некоторые другие альтернативы, подходящие для моего случая. Любая информация будет очень ценна.
12 ответов:
вы можете запустить свой PHP-скрипт из командной строки (т. е. bash) с помощью
nohup php myscript.php &the
&ставит свой процесс в фоновом режиме.Edit:
Да, есть некоторые недостатки, но не удается контролировать? Это просто неправильно.
Простойkill processidостановит его. И это по-прежнему лучшее и самое простое решение.
другой вариант-использовать выскочка. Изначально он был разработан для Ubuntu (и поставляется в комплекте по умолчанию), но предназначен для всех дистрибутивов Linux.
этот подход похож на Supervisord и daemontools, в том, что он автоматически запускает демон при загрузке системы и возрождается при завершении сценария.
как настроить его:
создать новый файл скрипта
/etc/init/myphpworker.conf. Вот пример:# Info description "My PHP Worker" author "Jonathan" # Events start on startup stop on shutdown # Automatically respawn respawn respawn limit 20 5 # Run the script! # Note, in this example, if your PHP script returns # the string "ERROR", the daemon will stop itself. script [ $(exec /usr/bin/php -f /path/to/your/script.php) = 'ERROR' ] && ( stop; exit 1; ) end scriptзапуск и остановка вашего демона:
sudo service myphpworker start sudo service myphpworker stopпроверьте, работает ли ваш демон:
sudo service myphpworker statusспасибо
большое спасибо Кевин ван Зонневельд, где я научился этой технике.
если вы можете - возьмите копию расширенное программирование в среде UNIX. Вся Глава 13 посвящена программированию демонов. Примеры находятся в C, но все функции, которые вам нужны, имеют обертки в PHP (в основном pcntl и posix расширения).
в нескольких словах-написание демона (это возможно только на * Nix OS-es - Windows использует службы) выглядит так:
- звоните
umask(0)для предотвращения проблем с разрешениями.fork()и есть родительский выход.- вызов
setsid().- настройка обработки сигнала
SIGHUP(обычно это игнорируется или используется для сигнала демону перезагрузить его конфигурацию) иSIGTERM(чтобы сказать процессу, чтобы выйти изящно).fork()снова и родительского ухода.- изменить текущий рабочий каталог с помощью
chdir().fclose()stdin,stdoutиstderrи не пишите им. Правильный способ-перенаправить их на любой/dev/nullили файл, но я не мог найти способ сделать это в PHP. Это возможно, когда вы запускаете демон, чтобы перенаправить их с помощью оболочки (вы должны будете узнать сами, как это сделать, я не знаю :).- делайте свою работу!
кроме того, так как вы используете PHP, будьте осторожны для циклических ссылки, так как сборщик мусора PHP, до PHP 5.3, не имеет возможности собирать эти ссылки, и процесс будет утечка памяти, пока он в конечном итоге не выйдет из строя.
новые systemd вы можете создать службу (на основе rhel linux).
вы должны создать файл или ссылка in
/etc/systemd/system/, например. myphpdaemon.сервис и разместить контент, как этот, myphpdaemon будет имя сервиса:[Unit] Description=My PHP Daemon Service #May your script needs mysql or other services to run, eg. mysql memcached Requires=mysqld.service memcached.service After=mysqld.service memcached.service [Service] User=root Type=simple TimeoutSec=0 PIDFile=/var/run/myphpdaemon.pid ExecStart=/usr/bin/php -f /srv/www/myphpdaemon.php arg1 arg2> /dev/null 2>/dev/null #ExecStop=/bin/kill -HUP $MAINPID #It's the default you can change whats happens on stop command #ExecReload=/bin/kill -HUP $MAINPID KillMode=process Restart=on-failure RestartSec=42s StandardOutput=null #If you don't want to make toms of logs you can set it null if you sent a file or some other options it will send all php output to this one. StandardError=/var/log/myphpdaemon.log [Install] WantedBy=default.targetвы сможете запускать, получать статус, перезапускать и останавливать службы с помощью команды
systemctl <start|status|restart|stop|enable> myphpdaemonPHP скрипт должен иметь своего рода "цикл", чтобы продолжайте бежать.
<?php gc_enable();// while (!connection_aborted() || PHP_SAPI == "cli") { //Code Logic //sleep and usleep could be useful if (PHP_SAPI == "cli") { if (rand(5, 100) % 5 == 0) { gc_collect_cycles(); //Forces collection of any existing garbage cycles } } }пример:
[Unit] Description=PHP APP Sync Service Requires=mysqld.service memcached.service After=mysqld.service memcached.service [Service] User=root Type=simple TimeoutSec=0 PIDFile=/var/run/php_app_sync.pid ExecStart=/bin/sh -c '/usr/bin/php -f /var/www/app/private/server/cron/app_sync.php 2>&1 > /var/log/app_sync.log' KillMode=mixed Restart=on-failure RestartSec=42s [Install] WantedBy=default.targetесли ваш PHP должен выполняться один раз в цикле (например, diggest) , вы можете использовать сценарий оболочки или bash для вызова в файл службы systemd вместо PHP напрямую, например:
#!/usr/bin/env bash script_path="/app/services/" while [ : ] do # clear php -f "$script_path"".php" fixedparameter > /dev/null 2>/dev/null sleep 1 doneесли вы выбрали эти опции вам нужно изменить KillMode до
mixedчтобы процессы, bash(main) и php (child) были убиты.ExecStart=/app/phpservice/runner.sh phpfile parameter > /dev/null 2>/dev/null KillMode=processПримечание: каждый раз что вы измените свой " myphpdaemon."вы должны запустите "systemctl daemon-reload", но не волнуйтесь, если вы этого не сделаете, это будет запрашивается, когда это необходимо.
Я запускаю большое количество PHP демонов.
Я согласен с вами, что PHP не является лучшим (или даже хорошим) языком для этого, но демоны разделяют код с веб-компонентами, поэтому в целом это хорошее решение для нас.
мы используем daemontools для этого. Это умный, чистый и надежный. На самом деле мы используем его для управления всеми нашими демонами.
вы можете проверить это на http://cr.yp.to/daemontools.html.
EDIT: A краткий список функций.
- автоматически запускает демон при перезагрузке
- автоматически перезапустить dameon при сбое
- ведение журнала обрабатывается для вас, включая опрокидывание и обрезку
- интерфейс управления: 'svc ' и'svstat'
- UNIX дружественный (не плюс для всех, возможно)
вы можете
- использовать
nohupКак предложил Хенрик.- использовать
screenи запустите свою PHP-программу как обычный процесс внутри этого. Это дает вам больше контроля, чем с помощьюnohup.- используйте демонизатор как http://supervisord.org/ (он написан на Python, но может демонизировать любую программу командной строки и дать вам пульт дистанционного управления для управления ею).
- напишите свою собственную обертку демонизма, как предложил Эмиль, но это перебор ММО.
Я бы рекомендовал самый простой метод (экран, на мой взгляд), а затем, если вы хотите больше возможностей или функциональности, перейдите к более сложным методам.
есть больше чем один способ решить эту проблему.
Я не знаю специфики, но, возможно, есть другой способ запустить процесс PHP. Например, если вам нужен код для запуска на основе событий в базе данных SQL, вы можете настроить триггер для выполнения вашего сценария. Это очень легко сделать в PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .
честно говоря, я думаю, что лучше всего создать процесс Деймона использование nohup. nohup позволяет команде продолжать выполнение даже после выхода пользователя из системы:
nohup php myscript.php &однако есть очень серьезная проблема. Как вы сказали, менеджер памяти PHP-это полный мусор, он был построен с предположением, что скрипт выполняется только в течение нескольких секунд, а затем существует. Ваш PHP скрипт начнет использовать гигабайты памяти уже через несколько дней. Вы также должны создать сценарий cron, который запускается каждые 12 или, возможно, 24 часа, который убивает и повторно порождает ваш PHP скрипт следующим образом:
killall -3 php nohup php myscript.php &но что, если сценарий был в середине работы? Ну kill -3-это прерывание, это то же самое, что делать ctrl+c на CLI. Ваш PHP скрипт может поймать это прерывание и выйти изящно с помощью библиотеки PHP pcntl:http://php.oregonstate.edu/manual/en/function.pcntl-signal.php
вот пример:
function clean_up() { GLOBAL $lock; mysql_close(); fclose($lock) exit(); } pcntl_signal(SIGINT, 'clean_up');идея $lock заключается в том, что php-скрипт может открыть файл с помощью fopen ("file","w");. Только один процесс может иметь блокировку записи на файл, поэтому с помощью этого вы можете убедиться, что работает только одна копия вашего PHP-скрипта.
Удачи!
Кевин ван Зонневельд написал очень хорошую подробную статью об этом в своем примере он использует
System_Daemonгруша пакет (дата последнего выпуска 2009-09-02).
проверить https://github.com/shaneharter/PHP-Daemon
это объектно-ориентированная библиотека демона. Он имеет встроенную поддержку для таких вещей, как ведение журнала и восстановление ошибок, и он имеет поддержку для создания фоновых рабочих.
недавно мне понадобилось кросс-платформенное решение (Windows, Mac и Linux) для проблемы запуска PHP-скриптов в качестве демонов. Я решил проблему, написав свое собственное решение на основе C++ и создав двоичные файлы:
https://github.com/cubiclesoft/service-manager/
полная поддержка Linux (через sysvinit), но также Windows NT services и Mac OSX launchd.
Если вам просто нужен Linux, то несколько других решений, представленных здесь работать достаточно хорошо и, в зависимости от вкуса. В наши дни также есть Upstart и systemd, которые имеют резервные копии сценариев sysvinit. Но половина смысла использования PHP заключается в том, что он является кросс-платформенным по своей природе, поэтому код, написанный на этом языке, имеет довольно хорошие шансы работать везде как есть. Недостатки начинают проявляться, когда некоторые внешние аспекты уровня собственной ОС входят в картину, такую как системные службы, но вы получите эту проблему с большинством сценариев языки.
попытка поймать сигналы, как кто-то здесь предложил в PHP userland не очень хорошая идея. Прочитайте документацию по
pcntl_signal()осторожно, и вы быстро узнаете, что PHP обрабатывает сигналы, используя некоторые довольно неприятные методы (в частности, "тики"), которые жуют кучу циклов для чего-то редко видимого процессами (т. е. сигналов). Обработка сигналов в PHP также едва доступна на платформах POSIX и поддержка отличается в зависимости от версии PHP. Это изначально звучит как достойное решение, но оно не очень полезно.PHP также становится лучше о проблемах утечки памяти во время игры. Вы все еще должны быть осторожны (парсер DOM XML имеет тенденцию к утечке все еще), но я редко вижу убегающие процессы в эти дни, и PHP-трекер ошибок довольно тих по сравнению с прежними днями.
Как уже упоминалось, запуск PHP в качестве демона довольно прост и может быть выполнен с помощью одной строки команды. Но реальная проблема заключается в том, чтобы держать его в рабочем состоянии и управлять им. У меня была такая же проблема довольно давно, и хотя уже есть много решений, большинство из них имеют много зависимостей или сложны в использовании и не подходят для основных применений. Я написал сценарий оболочки, который может управлять любым процессом/приложением, включая скрипты php cli. Оно может установите в качестве cronjob для запуска приложения и будет содержать приложение и управлять им. Если он выполняется снова, например, через тот же cronjob, он проверяет, работает ли приложение или нет, если это так, то просто выходит и позволяет его предыдущему экземпляру продолжать управлять приложением.
Я загрузил его в github, не стесняйтесь использовать его:https://github.com/sinasalek/EasyDeamonizer
EasyDeamonizer
просто наблюдает за вашей применение (старт, рестарт, журнал, монитор, ЕТК). универсальный сценарий, чтобы убедиться, что приложение работает правильно. Намеренно он использует имя процесса instread файла pid/lock, чтобы предотвратить все его побочные эффекты и сохранить сценарий как можно более простым и stirghforward, поэтому он всегда работает даже при перезапуске самого EasyDaemonizer. Особенности
- запускает приложение и, возможно, настроенную задержку для каждого запуска
- удостоверяется, что только один экземпляр работает
- контролирует использование ЦП и автоматически перезапускает приложение, когда оно достигает определенного порога
- установка EasyDeamonizer для запуска через cron, чтобы запустить его снова, если он остановлен по какой-либо причине
- регистрирует свою активность
Я написал и развернул простой php-демон, код здесь онлайн
https://github.com/jmullee/PhpUnixDaemon
особенности: сброс привилегий, обработка сигналов, ведение журнала
Я использовал его в обработчике очереди (случай использования: запуск длительной операции с веб-страницы, не заставляя php-генерацию страницы ждать, т. е. запускать асинхронную операцию) https://github.com/jmullee/PhpIPCMessageQueue
Comments