blog.bartlweb - a technologist's external brain

PHP-Skripte als Daemon mit systemd unter Linux als Services betreiben

PHP kann nicht nur als Skriptsprache für dynamische Websites genutzt werden, sondern auch als Programmiersprache für Hilfsprogramme oder asynchrone Server-Dienste wie z.B. einem Chatbot.

Damit die Skripte dann am Server auch entsprechend beim Systemstart gestartet werden und vor allem auch jederzeit entsprechend gestoppt oder neu gestartet werden können, lassen sich diese (wie jedes andere Programm auch) als Daemon mit systemd einrichten.

Daemon-Konfiguration erstellen

Dazu wird ein entsprechendes Init-Skript erstellt und unter /etc/init.d/ abgelegt. Der Name des Skriptes gibt den Namen des Daemons vor (stellen Sie sicher, dass Sie die Datei ohne Dateiendung erstellen, z.B. php-slackbot). Wichtig sind dann vor allem die Berechtigungen für die erstellte Datei. Nur wenn diese korrekt gesetzt sind, lässt sich der Daemon auch ausführen. Setzen Sie diese mit chmod +x /etc/init.d/<daemon>.

Der folgende Quellcode für das Init-Skript stellt die Befehle Start, Stop, Restart und Status, sowie ein entsprechendes Logging bereit. An die eigenen Bedürfnisse anzupassen sind die zu Beginn des Skripts definierten Variablen für den Namen des Daemons und die Pfade zum PHP-Interpreter bzw. dem eigentlichen PHP-Skript und dem Nutzer unter dem der Daemon ausgeführt werden soll. 

#! /bin/sh
 
### BEGIN INIT INFO
# Provides:          php-slackbot
# Required-Start:    $local_fs $remote_fs $network $syslog
# Required-Stop:     $local_fs $remote_fs $network $syslog
# Default-Start:     2 3 4 5
# Default-Stop:      0 1 6
# Short-Description: PHP script daemon for slackbot
# Description:       PHP script daemon for slackbot
#                    Installation:
#                    Copy this file to /etc/init.d/ (no file extension allowed)
#                    chmod +x this
#                    sudo update-rc.d <myservice> defaults 91 // because it must start after mysql
### END INIT INFO
 
NAME=php-slackbot
DESC="PHP script daemon for slackbot"
 
PIDFILE="/var/run/${NAME}.pid"
LOGFILE="/var/log/${NAME}.log"
 
DAEMON="/usr/bin/php"
DAEMON_OPTS="/server/chatbots/slack/bot.php"
 
RUN_AS=www

START_OPTS="--start --background --chuid ${RUN_AS} --make-pidfile --pidfile ${PIDFILE} --exec ${DAEMON} ${DAEMON_OPTS}"
STOP_OPTS="--stop --pidfile ${PIDFILE}"
 
. /lib/lsb/init-functions
test -x $DAEMON || exit 0
 
set -e
 
do_start()
{
    log_daemon_msg "Starting ${DESC}" "$NAME"
    start-stop-daemon $START_OPTS >> $LOGFILE
    log_end_msg $?
}
 
do_stop()
{
    if pidof $DAEMON > /dev/null 2>&1 ; then
        log_daemon_msg "Stopping ${DESC}" "$NAME"
        start-stop-daemon $STOP_OPTS
    else
        log_daemon_msg "$NAME is not running."
    fi
    log_end_msg $?
}
 
case "$1" in
    start)
        do_start
        ;;
    stop)
        do_stop
        ;;
    status)
        if [ -e $PIDFILE ]; then
            status_of_proc -p $PIDFILE $DAEMON "$NAME process" && exit 0 || exit $?
        else
            log_daemon_msg "$NAME Process is not running"
            log_end_msg 0
        fi
        ;;
    restart|force-reload)
        do_stop
        case "$?" in
            0|1)
                do_start
                ;;
            *)
                log_end_msg 1
                print_error_msg
                exit 1
                ;;
            esac
        ;;
    *)
        N=/etc/init.d/$NAME
        echo "Usage: $N {start|stop|status|restart|force-reload}" >&2
        exit 1
        ;;
esac
 
exit 0

Daemon für Autostart konfigurieren

Wie alle Daemons kann auch unser Daemon über update-rc.d so konfiguriert werden, dass dieser beim Systemstart automatisch ausgeführt wird. Zu beachten ist dabei allerdings die Startreihenfolge der einzelnen Daemons. In meinem PHP-Skript binde ich MySQL als Datenbank ein und musste daher sicherstellen, das MySQL vor meinem PHP-Daemon gestartet wird, um keine Fehler bei der Ausführung zu erhalten. Dazu habe ich einen entsprechend hohen Wert 91 als Parameter für den Sequenzcode defniert (20 ist der Standardwert, wenn kein Code angegeben wird).

update-rc.d <daemon> defaults 91

Dieser Artikel hat Dir deinen Tag gerettet?

... und mühevolles Probieren, Recherchieren und damit Stunden an Zeit gespart? Oder einfach nur Dein Problem gelöst?

Dann würde ich mich freuen, wenn Du meine Zeit für die Erstellung dieses Blogartikels mit einer kleinen Anerkennung honorierst:

Zahlung mit PayPal oder Kreditkarte.

Hinweis zur Verwendung

Die Übermittlung einer Zahlung ist eine persönliche Anerkennung Ihrerseits an den Entwickler (Christian Bartl, Privatperson). Eine Zahlung ist nicht zweckgebunden und es ist keine Gegenleistung zu erwarten. Bitte beachten Sie, dass für eine übermittelte Zahlung keine Quittung ausgestellt werden kann.

Über den Autor

Christian Bartl

Christian Bartl Requirements Engineer
& Solution Architect für Online und Mobile

Als Technologie-Enthusiast und begeisterter Programmierer entwickle ich in meiner Freizeit Websites, Software und IT-Lösungen, die mir selbst und anderen den Alltag vereinfachen.

mehr auf christian.bartl.me

Kommentare

  1. Wenn ich den Status des Daemon abfrage erhalte ich einen Fehler in der Zeile 44 und somit läuft es leider nicht.

    root@406914-ZFATorsten:/etc/init# /etc/init.d/php-test status

    ● php-test.service - LSB: PHP script daemon for php-test
    Loaded: loaded (/etc/init.d/php-test; generated; vendor preset: enabled)
    Active: failed (Result: exit-code) since Thu 2019-08-29 12:16:03 CEST; 11min ago
    Docs: man:systemd-sysv-generator(8)

    Aug 29 12:16:03 406914-ZFATorsten systemd[1]: Starting LSB: PHP script daemon for php-test...
    Aug 29 12:16:03 406914-ZFATorsten php-test[1529]: /etc/init.d/php-test: 44: /etc/init.d/php-test: Syntax error: "then" unexpected (expecting "}")
    Aug 29 12:16:03 406914-ZFATorsten systemd[1]: php-test.service: Control process exited, code=exited status=2
    Aug 29 12:16:03 406914-ZFATorsten systemd[1]: Failed to start LSB: PHP script daemon for php-test.
    Aug 29 12:16:03 406914-ZFATorsten systemd[1]: php-test.service: Unit entered failed state.
    Aug 29 12:16:03 406914-ZFATorsten systemd[1]: php-test.service: Failed with result 'exit-code'.

    kommentieren

    1. Hast Du hierfür vielleicht ein simples PHP-Script, welches als Daemon läuft `?

      kommentieren

    2. Hallo Torsten,
      das PHP-Skript muss natürlich endlos laufen können, z.B. mit React, damit es als Deamon funktioniert. Ein simples Testskript habe ich daher leider nicht zur Hand.
      lg Christian

      kommentieren

  2. Hallo,

    es reicht eigentlich schon ein Script, das in einer Endlosschleife wie while (true) { ... } läuft ... darauf achten, dass die max_execution_time == 0 entspricht entweder in der php.ini für die cli scripts oder über set_time_limit im script selbst. Besten Dank für den Artikel @Christian, funktioniert einwandfrei.

    Viele Grüsse,

    kommentieren

Kommentar schreiben

Der hier angegebene Name wird gemeinsam mit deinem Kommentar auf der Website veröffentlicht.

Deine E-Mail-Adresse wird zur einmaligen Benachrichtigung bei Veröffentlichung des Kommentars genutzt.

Benachrichtigung per E-Mail über Antworten auf meinen Kommentar erhalten.

Bitte tippe die Zahlenkombination "7968" ein, nur dann kann ich deinen Kommentar entgegennehmen.

Bitte fülle dieses Feld nicht aus, nur dann kann ich deinen Kommentar entgegennehmen.