Uruchom skrypt php jako proces demona

Muszę uruchomić skrypt php jako proces demona(czekać na instrukcje i robić rzeczy). cron job nie zrobi tego za mnie, ponieważ działania muszą zostać podjęte, gdy tylko pojawi się instrukcja. Wiem, że PHP nie jest najlepszym rozwiązaniem dla procesów demona ze względu na problemy z zarządzaniem pamięcią, ale z różnych powodów muszę używać PHP w tym przypadku. Natknąłem się na narzędzie libslack o nazwie Daemon ( http://libslack.org/daemon ) wydaje mi się, że pomaga mi zarządzać procesami daemona, ale nie było żadnych aktualizacje w ciągu ostatnich 5 lat, więc zastanawiam się, czy znasz jakieś inne alternatywy odpowiednie dla mojego przypadku. Wszelkie informacje będą naprawdę mile widziane.

Author: Darryl Hein, 2010-01-10

12 answers

Skrypt php można uruchomić z wiersza poleceń (np. bash) używając

nohup php myscript.php &

& umieszcza twój proces w tle.

Edit:
Tak, są pewne wady, ale nie można kontrolować? To jest złe.
Proste kill processid to powstrzyma. I to wciąż najlepsze i najprostsze rozwiązanie.

 153
Author: Henrik P. Hessel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-19 06:46:18

Inną opcją jest użycie Upstart . Pierwotnie został opracowany dla Ubuntu (i jest domyślnie pakowany z nim), ale ma być odpowiedni dla wszystkich dystrybucji Linuksa.

To podejście jest podobne doSupervisord i daemontools , ponieważ automatycznie uruchamia demona podczas rozruchu systemu i odradza się po zakończeniu skryptu.

Jak go skonfigurować:

Utwórz nowy plik skryptu w /etc/init/myphpworker.conf. Oto przykład:

# 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

Początek & zatrzymanie demona:

sudo service myphpworker start
sudo service myphpworker stop

Sprawdź, czy twój Demon działa:

sudo service myphpworker status

Dzięki

Wielkie podziękowania dla Kevina van zonnevelda, od którego nauczyłem się tej techniki.
 143
Author: Jonathan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-16 20:05:53

Jeśli możesz - pobierz kopię Advanced Programming in the UNIX Environment. Cały rozdział 13 poświęcony jest programowaniu daemon. Przykłady są w języku C, ale wszystkie potrzebne funkcje mają wrappery w PHP (zasadniczo rozszerzenia pcntl i posix).

W kilku słowach-pisanie demona (jest to możliwe tylko w systemie operacyjnym *opartym na nix - es-Windows używa usług) jest takie:

  1. Call umask(0) aby zapobiec uprawnieniom problemy.
  2. fork() i mieć wyjście dla rodziców.
  3. Call setsid().
  4. Ustawia przetwarzanie sygnału SIGHUP (zwykle jest to ignorowane lub używane do sygnalizowania demona, aby ponownie załadował konfigurację) i SIGTERM (aby powiedzieć procesowi, aby z wdziękiem zakończył pracę).
  5. fork() ponownie i mieć wyjście nadrzędne.
  6. Zmień bieżący katalog roboczy z chdir().
  7. fclose() stdin, stdout i nie pisz do nich. Corrrect sposób jest aby przekierować je do /dev/null lub pliku, ale nie mogłem znaleźć sposobu, aby to zrobić w PHP. Jest to możliwe, gdy uruchomisz demona przekierować je za pomocą powłoki (będziesz musiał sam się dowiedzieć, jak to zrobić, Nie wiem :).
  8. Rób swoje!

Również, ponieważ używasz PHP, należy uważać na cykliczne odwołania, ponieważ PHP garbage collector, przed PHP 5.3, nie ma możliwości zbierania tych odwołań i proces będzie wyciek pamięci, aż w końcu awarie.

 45
Author: Emil Ivanov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-15 21:42:57

Z nowym systemd możesz utworzyć usługę (na Linuksie opartym na rhel).

Musisz utworzyć plik lub symlink w /etc/systemd/system/, np. myphpdaemon.serwis i umieść taką treść, myphpdaemon będzie nazwą serwisu:

[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

Będziesz mógł uruchomić, uzyskać status, zrestartować i zatrzymać usługi za pomocą polecenia

systemctl <start|status|restart|stop|enable> myphpdaemon

Skrypt PHP powinien mieć rodzaj "pętli", aby kontynuować działanie.

<?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
        }
    }
}

Praca przykład:

[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

Jeśli Twoje PHP powinno być wykonywane raz w cyklu (jak diggest), możesz użyć skryptu powłoki lub bash, który zostanie wywołany do pliku usługi systemd zamiast PHP bezpośrednio, na przykład:

#!/usr/bin/env bash
script_path="/app/services/"

while [ : ]
do
#    clear
    php -f "$script_path"${1}".php" fixedparameter ${2}  > /dev/null 2>/dev/null
    sleep 1
done

Jeśli wybrałeś tę opcję powinieneś zmienić KillMode na mixed na procesy, bash(main) i php(child) zostaną zabite.

ExecStart=/app/phpservice/runner.sh phpfile parameter  > /dev/null 2>/dev/null
KillMode=process

Uwaga: za każdym razem, gdy zmienisz swój " myphpdaemon.serwis " musisz Uruchom 'systemctl daemon-reload' , ale zrób martw się, jeśli tego nie zrobisz, to będzie monit, gdy jest to potrzebne.

 35
Author: LeonanCarvalho,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-08-22 13:29:52

Uruchamiam dużą liczbę demonów PHP.

Zgadzam się z Tobą, że PHP nie jest najlepszym (a nawet dobrym) językiem do tego, ale demony dzielą kod z komponentami sieciowymi, więc ogólnie jest to dobre rozwiązanie dla nas.

Używamy do tego daemontools. Jest Inteligentny, czysty i niezawodny. W rzeczywistości używamy go do uruchamiania wszystkich naszych demonów.

Możesz to sprawdzić na http://cr.yp.to/daemontools.html .

EDIT: szybka lista funkcje.

  • automatycznie uruchamia demona przy ponownym uruchomieniu
  • automatycznie uruchom ponownie dameon po awarii
  • Logowanie jest obsługiwane dla Ciebie, w tym rollover i przycinanie
  • interfejs zarządzania: 'svc' i 'svstat'
  • przyjazny dla Uniksa (chyba nie dla każdego)
 23
Author: Phil Wallach,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-19 01:28:11

Możesz

  1. Użyj nohup jak zasugerował Henrik.
  2. Użyj screen i uruchom swój program PHP jako zwykły proces wewnątrz niego. Daje to większą kontrolę niż użycie nohup.
  3. Użyj daemonisera jak http://supervisord.org/ (jest napisany w Pythonie, ale może demonizować dowolny program wiersza poleceń i dać ci pilota do zarządzania nim).
  4. napisz własne opakowanie daemonise jak zasugerował Emil, ale IMO to przesada.
Polecam najprostsza metoda (moim zdaniem screen), a następnie, jeśli chcesz więcej funkcji lub funkcjonalności, przejdź do bardziej złożonych metod.
 14
Author: Noufal Ibrahim,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-19 07:09:02

Jest więcej niż jeden sposób na rozwiązanie tego problemu.

Nie znam szczegółów, ale być może istnieje inny sposób na uruchomienie procesu PHP. Na przykład, jeśli potrzebujesz kodu do uruchomienia w oparciu o zdarzenia w bazie danych SQL, możesz skonfigurować wyzwalacz do wykonania skryptu. Jest to naprawdę łatwe do zrobienia pod PostgreSQL: http://www.postgresql.org/docs/current/static/external-pl.html .

Szczerze mówiąc, myślę, że najlepiej będzie stworzyć proces Damona za pomocą nohup. nohup pozwala na kontynuowanie wykonywania polecenia nawet po wylogowaniu się użytkownika:
nohup php myscript.php &
Jest jednak bardzo poważny problem. Jak powiedziałeś Menedżer pamięci PHP jest kompletnym śmieciem, został zbudowany z założeniem, że skrypt jest wykonywany tylko przez kilka sekund, a następnie istnieje. Twój skrypt PHP zacznie używać gigabajtów pamięci już po kilku dniach. Musisz również utworzyć skrypt cron, który działa co 12 lub Może 24 godzin, który zabija i ponownie pojawia się twój skrypt php jak to:
killall -3 php
nohup php myscript.php &
A gdyby scenariusz był w trakcie pracy? Dobrze zabić -3 jest przerwaniem, to samo, co robi ctrl + c na CLI. Twój skrypt php może przechwycić to przerwanie i zakończyć z wdziękiem za pomocą biblioteki PHP pcntl: http://php.oregonstate.edu/manual/en/function.pcntl-signal.php

Oto przykład:

function clean_up() {
  GLOBAL $lock;
  mysql_close();
  fclose($lock)
  exit();
}
pcntl_signal(SIGINT, 'clean_up');

Idea $lock polega na tym, że skrypt PHP może otworzyć plik za pomocą fopen ("file","w");. Tylko jeden proces może mieć blokadę zapisu na pliku, więc używając tego możesz upewnić się, że działa tylko jedna kopia twojego skryptu PHP.

Powodzenia!
 11
Author: rook,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-12-19 01:30:54

Kevin van Zonneveld napisał bardzo ładny szczegółowy artykuł na ten temat , w swoim przykładzie wykorzystuje System_Daemon PEAR package (ostatnia data premiery: 2009-09-02).

 10
Author: Alix Axel,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2010-01-15 15:19:21

Sprawdź https://github.com/shaneharter/PHP-Daemon

Jest to obiektowo zorientowana biblioteka demona. Ma wbudowaną obsługę takich rzeczy, jak rejestrowanie i odzyskiwanie błędów, a także wsparcie dla tworzenia pracowników w tle.

 6
Author: Shane H,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-02-16 00:30:34

Ostatnio potrzebowałem wieloplatformowego rozwiązania (Windows, Mac i Linux) problemu uruchamiania skryptów PHP jako demonów. Rozwiązałem ten problem pisząc własne rozwiązanie oparte na C++ i tworząc binaria:

Https://github.com/cubiclesoft/service-manager/

Pełne wsparcie dla Linuksa (przez sysvinit), ale także Windows NT services i Mac OSX launchd.

Jeśli potrzebujesz tylko Linuksa, to kilka innych przedstawionych tutaj rozwiązań działa wystarczająco dobrze i, w zależności od smaku. Istnieje również Upstart i systemd te dni, które mają zamienniki do skryptów sysvinit. Ale połowa punktu korzystania z PHP jest to, że ma charakter wieloplatformowy, więc kod napisany w języku ma całkiem spore szanse na działanie wszędzie tak, jak jest. Braki pojawiają się, gdy pojawiają się pewne zewnętrzne aspekty natywne na poziomie systemu operacyjnego, takie jak usługi systemowe, ale problem pojawia się w większości języków skryptowych.

Próba wyłapania sygnałów jako ktoś tutaj zasugerował w PHP userland nie jest dobrym pomysłem. Przeczytaj uważnie dokumentację pcntl_signal(), a szybko dowiesz się, że PHP obsługuje sygnały za pomocą dość nieprzyjemnych metod (w szczególności 'kleszczy'), które żują kilka cykli na coś rzadko widzianego przez procesy (np. sygnały). Obsługa sygnałów w PHP jest również ledwo dostępna na platformach POSIX, a obsługa różni się w zależności od wersji PHP. Początkowo brzmi to jak przyzwoite rozwiązanie, ale spada dość krótko być naprawdę użytecznym.

PHP jest również coraz lepsze w kwestiach wycieku pamięci w miarę upływu czasu. Nadal musisz być ostrożny (parser XML DOM ma tendencję do wycieku nadal), ale rzadko widzę uciekających procesów tych dni i PHP bug tracker jest dość cichy w porównaniu do dni yore.

 3
Author: CubicleSoft,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-11 21:59:57

Jak już wspomnieli inni, uruchamianie PHP jako demona jest dość proste i można to zrobić za pomocą jednej linii poleceń. Ale prawdziwym problemem jest utrzymanie go w ruchu i zarządzanie nim. Miałem ten sam problem już jakiś czas temu i chociaż rozwiązań jest już dostępnych wiele, większość z nich ma wiele zależności lub są trudne w użyciu i nie nadają się do podstawowych zastosowań. Napisałem skrypt powłoki, który może zarządzać dowolnym procesem / aplikacją, w tym skryptami PHP cli. Może być Ustaw jako cronjob, aby uruchomić aplikację i będzie zawierać aplikację i zarządzać nią. Jeśli zostanie wykonana ponownie, na przykład za pomocą tego samego cronjob, sprawdza, czy aplikacja jest uruchomiona, czy nie, jeśli tak, to po prostu kończy działanie i pozwala poprzedniej instancji kontynuować zarządzanie aplikacją.

Wgrałem go na github, zapraszam do korzystania z niego : https://github.com/sinasalek/EasyDeamonizer

EasyDeamonizer

Po prostu czuwa nad twoją aplikacją (start, restart, log, monitor, itp.). ogólny skrypt, aby upewnić się, że aplikacja nadal działa poprawnie. Celowo używa nazwy procesu instread pliku PID / lock, aby zapobiec wszystkim jego skutkom ubocznym i utrzymać skrypt tak prosty i jak najbardziej stirghforward, więc zawsze działa nawet po ponownym uruchomieniu easydaemonizer. Cechy

  • uruchamia aplikację i Opcjonalnie Spersonalizowane opóźnienie dla każdego startu
  • upewnia się, że działa tylko jedna instancja
  • Monitory CPU użycie i ponowne uruchomienie aplikacji automatycznie po osiągnięciu zdefiniowanego progu
  • ustawienie EasyDeamonizer do uruchomienia przez cron, aby uruchomić go ponownie, jeśli zostanie zatrzymany z jakiegokolwiek powodu
  • rejestruje swoją aktywność
 1
Author: Sina Salek,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-05-20 11:11:05

Napisałem i wdrożyłem prosty PHP-daemon, kod jest online tutaj

Https://github.com/jmullee/PhpUnixDaemon

Funkcje: upuszczanie uprawnień, obsługa sygnałów, logowanie

Użyłem go w obsłudze kolejki (przypadek użycia: wyzwalanie długiej operacji ze strony internetowej, bez czekania na generowanie strony php, tzn. uruchamianie operacji asynchronicznej) https://github.com/jmullee/PhpIPCMessageQueue

 0
Author: jmullee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-30 14:30:52