Как запустить php-скрипт как процесс-демон
Мне нужно запустить php-скрипт в качестве процесса-демона (для ожидания инструкций и делать еще что-то). Задание cron не подойдет, потому что действия должны быть предприняты сразу после получения инструкции. Я знаю, что PHP — не самый лучший вариант для процессов-демонов из-за проблем с управлением памятью, но по разным причинам я должен использовать PHP для моего случая. Я наткнулся на инструмент от libslack под названием Daemon (http://libslack.org/daemon), который, кажется, помогает мне управлять процессами демона, но за последние 5 лет не было никаких обновлений, поэтому мне интересно, знаете ли вы другие альтернативы, подходящие для моего случая. Любая информация будет очень полезной.
Ответ 1
Вы можете запустить свой php-скрипт из командной строки (т . е . bash), используя:
nohup php myscript.php &
«&» переводит ваш процесс в фоновый режим.
Ответ 2
Другой вариант — использовать Upstart. Он был изначально разработан для Ubuntu (и поставляется с ним по умолчанию), но предназначен для всех дистрибутивов Linux. Этот подход похож на Supervisord и daemontools, поскольку он автоматически запускает демон при загрузке системы и возобновляет работу по завершении сценария.
Как настроить:
Создайте новый файл сценария в /etc/init/myphpworker.conf. Вот пример:
# Информация
description «My PHP Worker»
author «Jonathan»
# События
start on startup
stop on shutdown
# Автоматический ответ
respawn
respawn limit 20 5
# Запуск скрипта!
# Обратите внимание, что в этом примере, если ваш PHP скрипт возвращает
# строку «ERROR», демон остановится сам.
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
Ответ 3
С новым systemd вы можете создать сервис.
Вы должны создать файл или символическую ссылку на /etc/systemd/system/ , например , myphpdaemon.service , и разместить контент, подобный этому, myphpdaemon будет именем службы:
[Unit]Description=My PHP Daemon Service
#Может быть, вашему скрипту нужен MySQL или другие сервисы для работы, например, 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
#ExecReload=/bin/kill -HUP $MAINPID
KillMode=process
Restart=on-failure
RestartSec=42s
StandardOutput=null #Если вы не хотите делать тома логов, вы можете установить его в null, если вы отправили файл или другие опции, он будет отправлять весь вывод php в этот файл.
StandardError=/var/log/myphpdaemon.log
[Install]WantedBy=default.target
Вы сможете запускать, получать статус, перезапускать и останавливать службы с помощью команды:
systemctl
Сценарий PHP должен иметь своего рода «цикл» для продолжения работы.
gc_enable();//
while (!connection_aborted() || PHP_SAPI == «cli»)
//sleep и usleep могут быть полезны
if (PHP_SAPI == «cli»)
if (rand(5, 100) % 5 == 0)
gc_collect_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 должна выполняться один раз, вы можете использовать сценарий оболочки или bash, который будет вызываться в служебный файл systemd, а не напрямую в PHP, например:
#!/usr/bin/env bash
script_path=»/app/services/»
while [ : ]
do
# очистка
php -f «$script_path»$».php» fixedparameter $ > /dev/null 2>/dev/null
sleep 1
done
Если вы выбрали эту опцию, вы должны изменить KillMode для процессов mixed . bash (основной) и PHP (дочерний) будут завершены.
ExecStart=/app/phpservice/runner.sh phpfile parameter > /dev/null 2>/dev/null
KillMode=process
Этот метод также эффективен, если вы столкнулись с утечкой памяти.
Ответ 4
- Вызовите umask(0) для предотвращения проблем с разрешениями.
- Вызовите fork() и заставьте родительский процесс завершиться.
- Вызовите setid().
- Настройте обработку сигналов SIGHUP (обычно этот сигнал игнорируется или используется для сигнализации демону о необходимости перезагрузки его конфигурации) и SIGTERM (чтобы сообщить процессу о завершении).
- Снова выполните fork() и попросите родительский процесс завершиться.
- Измените текущий рабочий каталог с помощью chdir().
- fclose() stdin, stdout и stderr , и не пишите в них. Правильный способ — перенаправить их либо в /dev/null, либо в файл, но я не смог найти способ сделать это в PHP. Возможно, при запуске демона их можно перенаправить с помощью оболочки.
Ответ 5
- Автоматический запуск демона при перезагрузке .
- Автоматический перезапуск демона при сбое .
- Ведение журнала, включая перенос и обрезку.
- Интерфейс управления: ‘svc’ и ‘svstat’ .
- Дружественный к UNIX (возможно, не для всех это плюс) .
Ответ 6
Существует несколько способов решения этой проблемы. Я не знаю вашей специфики, но, возможно, есть другой способ запустить процесс PHP. Например, если вам нужно, чтобы код выполнялся на основе событий в базе данных SQL, вы можете настроить триггер для выполнения вашего скрипта. Это очень просто сделать в PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html.
Я думаю, что лучше всего создать процесс D ae mon с помощью 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-скрипта.
Ответ 7
Недавно мне понадобилось крос сп латформенное решение (Windows, Mac и Linux) для проблемы запуска PHP-скриптов в качестве демонов. Я решил эту проблему, написав собственное решение на основе C++ и создав двоичные файлы:
https://github.com/cubiclesoft/service-manager/
Полная поддержка Linux (через sysvinit), а также сервисов Windows и Mac OSX launchd.
Если вам нужен только Linux, то пара других решений, представленных здесь, работают достаточно хорошо. В наши дни есть также Upstart и systemd, которые имеют откат к скриптам sysvinit. Но смысл в использовани и PHP в том, что он кроссплатформенный по своей природе, поэтому код, написанный на этом языке, имеет довольно хорошие шансы работать везде как есть. Недостатки начинают проявляться, когда в дело вступают некоторые внешние аспекты на уровне ОС, такие как системные службы, но с этой проблемой сталкивается большинство скриптовых языков.
Попытка поймать сигнал ы в пользовательской среде PHP — не самая лучшая идея. Внимательно прочитайте документацию по pcntl_signal(), и вы быстро узнаете, что PHP обрабатывает сигналы, используя некоторые довольно неприятные методы (в частност и ‘ ticks’), которые поглощают кучу циклов для чего-то, редко встречающегося процессам (т . е . сигналов). Обработка сигналов в PHP также практически не доступна на POSIX — платформах, а поддержка зависит от версии PHP. Изначально это звучит как достойное решение, но до настоящей полезности ему далеко.
Со временем PHP также стал лучше справляться с проблемами утечки памяти. Вы все еще должны быть осторожны (парсер DOM XML все еще склонен к утечкам).
Мы будем очень благодарны
если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.
How to create a PHP linux daemon (service)
There are many ways to automate scripts and applications running on Linux, you can obviously create a cron task, that can execute from between a minute to once a year if you wanted there are however other ways in which you can have unattended background tasks execute.
Today I will explain how you can create a Linux daemon using ‘Upstart’, this tutorial has been carried out on Ubuntu Server 14.04 and will work with various other distributions too. If you wish to find out more about Upstart check out it’s project website.
To demonstrate it works we will create a small PHP script that will literally append a text file with a timestamp every couple of seconds!
A few benefits of running a PHP script as a daemon as opposed to a cron task are as follows:-
- You can easily start and stop the execution of these scripts without having to edit the crontab each time (simply issue a single command like ‘stop my-service-name’).
- You can run tasks more frequently than once per minute (which is currently the crontab’s minimum execution winow)
- Specify which run-levels your script is to be run on.
- …plus various others!
It is actually amazingly easy to create a Linux daemon using Upstart, you simply create a daemon configuration script under /etc/init (take not, NOT /etc/init.d as per the older System-V init scripts )
This is what our service script will look like, its pretty simple, there are many more awesome directives you can use for your service configuration script such as ‘pre-start’ configuration so your service can go and create initial directories or file etc. that it may depend on (check out the Upstart documentation for a full list of configuration directives.)
description "Bobbys Test Daemon" author "Bobby Allen" start on startup stop on shutdown respawn script sudo -u root php -f /usr/share/test_daemon.php end script
As you can see, we reference our PHP script within the configuration file, this is what will be run by the service, keep in mind that a daemon/service is designed to be ran continuously in the background and will only stop when told to.
You must keep in mind that you must develop your PHP service script to ‘loop’ continuously as by default a PHP script will run once and then exit out, here is a very quick example script of which should be placed on the filesystem somewhere and then referenced accordingly, in my example I’ve just placed it under /usr/share/test_daemon.php
The contents of the PHP script is as follows:-
You should now be able to start, stop and view the status of your new linux daemon like so:-
status test-daemon start test-daemon stop test-daemon
If you start the daemon using the command ‘start test-daemon‘ and give it 10 seconds, then stop it using ‘stop test-daemon‘ you should notice when you read the log file that our daemon is writing to every 2 seconds then it should include 5 lots of timestamps proving that the daemon is working successfully! (obviously it will have more if you’ve already been playing with the start command :))