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
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'.