Systemd php script daemon

Как запустить 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. Вот пример:

# Информация

Читайте также:  Google chrome включить java

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 myphpdaemon

Сценарий 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

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

Ответ 5

  1. Автоматический запуск демона при перезагрузке .
  2. Автоматический перезапуск демона при сбое .
  3. Ведение журнала, включая перенос и обрезку.
  4. Интерфейс управления: ‘svc’ и ‘svstat’ .
  5. Дружественный к 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 все еще склонен к утечкам).

Мы будем очень благодарны

если под понравившемся материалом Вы нажмёте одну из кнопок социальных сетей и поделитесь с друзьями.

Источник

Run php script as systemd service in centos7

Executing /usr/bin/php /var/www/htdocs/mysite/public/index.php abc xyz from linux commandline works as expected. only the systemd script doesnt work.

3 Answers 3

As an alternative, I’ve created a myphp.sh bash script

#!/bin/bash nohup /usr/bin/php /var/www/htdocs/mysite/public/index.php abc xyz & >> /var/log/custom.log 2>&1 

and then in systemd script

[Unit] Description=custom Service After=network.target [Service] Type=forking User=root ExecStart=/etc/init.d/myphp.sh [Install] WantedBy=multi-user.target 

Give a try with this configuration

[Service] Type=forking User=root PHP_PARAM_1=abc PHP_PARAM_2=xyz ExecStart=/usr/bin/php /var/www/htdocs/mysite/public/index.php $PHP_PARAM_1 $PHP_PARAM_2>> /var/log/custom.log 2>&1 
[Service] Type=forking User=root Environment="abc xyz" ExecStart=/usr/bin/php /var/www/htdocs/mysite/public/index.php $PHP_PARAM_1 $PHP_PARAM_2>> /var/log/custom.log 2>&1 

ExecStart does not support shell features like redirection. It’s what would be passed to execve() , which is just a path to a program and a list of arguments, separated by spaces. That’s why this doesn’t work.

This is but a hunch, but I think the prefix in the ExecStart option ( /usr/bin/php . ) is messing up the argument ordering and that’s why you cant use those args properly. I suspect you can mitigate this issue by using a shebang in your php script:

You also need to add exec rights to the files. This way, you can use the php script just like any other shell script, so you can just simply omit the prefix part from your ExecStart parameter:

ExecStart=/var/www/htdocs/mysite/public/index.php $PHP_PARAM_1 $PHP_PARAM_2 >> /var/log/custom.log 2>&1 

Источник

How To Create A PHP Daemon (Simple Examples)

Welcome to a quick tutorial on how to create a PHP daemon. Need to run a “service” PHP script in the background? Send out emails, fetch updates, or monitor something?

  • Set the script to run infinitely – while (true) < /* DO SOMETHING */ sleep(1); >
  • Then run in the command line – php DAEMON.PHP

Let us walk through a few examples in this guide – Read on!

TLDR – QUICK SLIDES

PHP Daemon Simple Example

TABLE OF CONTENTS

SIMPLE PHP DAEMON EXAMPLES

All right, let us now get into some simple examples of PHP daemons.

PRELUDE) COMMAND LINE CHECK

 if (defined("STDIN")) < return true; >if (array_key_exists("SHELL", $_ENV)) < return true; >if (!array_key_exists("REQUEST_METHOD", $_SERVER)) < return true; >if (empty($_SERVER["REMOTE_ADDR"]) && !isset($_SERVER["HTTP_USER_AGENT"]) && count($_SERVER["argv"])>0) < return true; >return false; > if (!is_cli())

Before we get into the examples, here is a quick snippet to check if the PHP “daemon script” is launched from the command line.

  • php_sapi_name()===»cli» The most recommended solution all over the Internet, but it is not always cli when the script is run as a scheduled task.
  • defined(«STDIN») “Standard input” is only available when the script is launched in CLI, but this is not always the case again.
  • $_ENV[«SHELL»] “Shell” is a “CLI-only” environment variable.
  • $_SERVER[«REQUEST_METHOD»] The HTTP request method only exists when the script is run through the web.
  • empty($_SERVER[«REMOTE_ADDR»]). Yet another common check recommended on the Internet.

Take note that it may not be 100% accurate despite all these checks, but it’s good enough. As to why we do a “command-line check”:

  • Security. Daemon scripts are supposed to be “background services”, not “scripts that are accessible on the Internet”.
  • Dummy proofing. To prevent newbies from putting and launching the daemon script on the Internet.

If you want to launch the daemon from an Intranet website or something, feel free to omit this check entirely.

EXAMPLE 1) BASIC MECHANICS

Yep, that’s all for the “basics of a daemon script” in PHP. Just run this script in the command line php 1-basic.php , and it will output It works! every 5 seconds. Not very useful, so let’s go through more practical examples below.

EXAMPLE 2) FETCH DATA FROM API

 else < echo $result . PHP_EOL; $result = json_decode($result, true); // $sql = "UPDATE `rates` SET `EUR` = ?"; // $sql = "UPDATE `rates` SET `GBP` = ?"; >// (C3) NEXT CYCLE curl_close($ch); sleep(CYCLE_PAUSE); > 
  • Use CURL to fetch the latest exchange rate from another server/service.
  • Then update the rates in the local database.

EXAMPLE 3) SERVER MONITORING

 // (D) START! logger("Start monitoring"); while (true) < // (D1) CURL TEST FETCH $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, CHECK_URL); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $result = curl_exec($ch); // (D2) RESULT if (curl_errno($ch)) < logger(curl_error($ch)); >else < $info = curl_getinfo($ch); logger($info["http_code"]." - ".$info["total_time_us"]); >// (D3) NEXT CYCLE curl_close($ch); sleep(CYCLE_PAUSE); >

Источник

Оцените статью