Запустите php скрипт как демон процесса



Мне нужно запустить PHP-скрипт в качестве демона процесса (ждать инструкций и делать вещи). хрон не будет делать это для меня потому, что меры должны быть приняты, как только инструкция прибывает. Я знаю, что PHP не самый лучший вариант для процессов демона из-за проблем с управлением памятью, но по разным причинам я должен использовать PHP в этом случае. Я наткнулся на инструмент libslack под названием Daemon (http://libslack.org/daemon) кажется, это помогает мне управлять процессами демона, но нет никаких обновлений за последние 5 лет, поэтому мне интересно, если вы знаете, некоторые другие альтернативы, подходящие для моего случая. Любая информация будет очень ценна.

974   12  

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 использует службы) выглядит так:

  1. звоните umask(0) для предотвращения проблем с разрешениями.
  2. fork() и есть родительский выход.
  3. вызов setsid().
  4. настройка обработки сигнала SIGHUP (обычно это игнорируется или используется для сигнала демону перезагрузить его конфигурацию) и SIGTERM (чтобы сказать процессу, чтобы выйти изящно).
  5. fork() снова и родительского ухода.
  6. изменить текущий рабочий каталог с помощью chdir().
  7. fclose()stdin,stdout и stderr и не пишите им. Правильный способ-перенаправить их на любой /dev/null или файл, но я не мог найти способ сделать это в PHP. Это возможно, когда вы запускаете демон, чтобы перенаправить их с помощью оболочки (вы должны будете узнать сами, как это сделать, я не знаю :).
  8. делайте свою работу!

кроме того, так как вы используете 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> myphpdaemon

PHP скрипт должен иметь своего рода "цикл", чтобы продолжайте бежать.

<?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 дружественный (не плюс для всех, возможно)

вы можете

  1. использовать nohup Как предложил Хенрик.
  2. использовать screen и запустите свою PHP-программу как обычный процесс внутри этого. Это дает вам больше контроля, чем с помощью nohup.
  3. используйте демонизатор как http://supervisord.org/ (он написан на Python, но может демонизировать любую программу командной строки и дать вам пульт дистанционного управления для управления ею).
  4. напишите свою собственную обертку демонизма, как предложил Эмиль, но это перебор ММО.

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

есть больше чем один способ решить эту проблему.

Я не знаю специфики, но, возможно, есть другой способ запустить процесс 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

    Ничего не найдено.