Der Debian-Dienst startet die Datei beim Start nicht richtig

Der Debian-Dienst startet die Datei beim Start nicht richtig

Ich habe eine Datei mit diesem Inhalt botstart.serviceaufgerufen :/etc/systemd/system

[Unit]
Description=Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) and the lavalink server.

[Service]
ExecStart=/bin/bash /home/scripts/start.sh

[Install]
WantedBy=multi-user.target

Ich habe es mit gestartet systemctl enable botstart und es wurde angezeigt, dass es aktiviert ist. Ich habe meinen VPS neu gestartet, aber das Skript wurde nicht ausgeführt. Ich habe es getan systemctl status botstartund es wurde Folgendes angezeigt:

root@Hetzner-01:~# systemctl status botstart
● botstart.service - Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper)
   Loaded: loaded (/etc/systemd/system/botstart.service; enabled; vendor preset:
   Active: inactive (dead) since Wed 2021-10-27 01:37:10 CEST; 50s ago
  Process: 481 ExecStart=/bin/bash /home/scripts/start.sh (code=eited, status=0
 Main PID: 481 (code=existed, status=0/SUCCESS)

Oct 27 01:37:07 Hetzner-01 systemd[1]: STarted Start all discord bots (antiSpam,
Oct 27 01:37:10 Hetzner-01 bash[481]: Started all bots
Oct 27 01:37:10 Hetzner-01 systemd[1]: botstart.service: Succeeded.
lines 1-9/9 (END)...skipping...
● botstart.service - Start all discord bots (AntiSpam, AutoChat, Nyoko, Helper) and the lavalink server.
   Loaded: loaded (/etc/systemd/system/botstart.service; enabled; vendor preset: enabled)
   Active: inactive (dead) since Wed 2021-10-27 01:37:10 CEST; 50s ago
  Process: 481 ExecStart=/bin/bash /home/scripts/start.sh (code=eited, status=0/SUCCESS)
 Main PID: 481 (code=existed, status=0/SUCCESS)

Wenn ich das Skript manuell ausführe, funktioniert es, aber irgendwie nicht als Dienst, sondern der Dienst wird ausgeführt und das Skript läuft (das sagt mir der Dienststatus). Weiß jemand warum? Dies ist der Skriptcode:

screen -dmS antispam bash -c "cd /home/AntiSpam; python3.8 main.py"
screen -dmS autochat bash -c "cd /home/AutoChat; python3.8 main.py"
screen -dmS helper bash -c "cd /home/Helper; python3.8 main.py"
screen -dmS lavalink bash -c "cd /home/Lavalink; python3.8 main.py"
sleep 3
screen -dmS nyoko bash -c "cd /home/Nyoko; python3.8 main.py"
echo "Started all bots"

Antwort1

In Ihrem [Service]Abschnitt haben Sie nicht explizit ein definiert Type=. Dies bedeutet, dass standardmäßig ein verwendet wird Type=simple.

Auf der Manpage steht:

Wenn auf „simple“ gesetzt, betrachtet der Servicemanager die Einheit als gestartet, unmittelbar nachdem der Hauptserviceprozess abgezweigt wurde. Es wird erwartet, dass der mit ExecStart= konfigurierte Prozess der Hauptprozess des Services ist....

Kurz gesagt, Ihr Skript ist der Hauptprozess. Es startet eine Reihe von Prozessen und wird dann beendet. systemdEs sieht, wie Ihr Hauptprozess beendet wird, und bereinigt dann die untergeordneten Prozesse, die keinen übergeordneten Prozess mehr haben.

Stattdessen möchten Sie Type=forking.

Wenn auf Forking eingestellt, wird erwartet, dass der mit ExecStart= konfigurierte Prozess beim Start fork() aufruft. Der übergeordnete Prozess wird voraussichtlich beendet, wenn der Start abgeschlossen ist und alle Kommunikationskanäle eingerichtet sind. Der untergeordnete Prozess wird weiterhin als Hauptdienstprozess ausgeführt, und der Dienstmanager betrachtet die Einheit als gestartet, wenn der übergeordnete Prozess beendet wird. Dies ist das Verhalten traditioneller UNIX-Dienste. Wenn diese Einstellung verwendet wird, wird empfohlen, auch die Option PIDFile= zu verwenden, damit systemd den Hauptprozess des Dienstes zuverlässig identifizieren kann.

In diesem Fall können Ihre untergeordneten Prozesse auch nach Beendigung Ihres Skripts weiterlaufen. Wenn Sie hinzufügen Type=forking, sollte es für Sie besser funktionieren.


Beachten Sie, dass Ihr Entwurf noch weitere Probleme aufweist. Wenn Sie nur Folgendes ändern Type=forking, haben Sie noch einige Probleme:

  • Wenn einer der Prozesse beendet wird, kann systemd entscheiden, dass dies die MainPID ist, oder auch nicht, und Ihren gesamten Dienst als betrachten inactive (dead). Das Schreiben in a PIDFile=kann dabei helfen, aber ich vermute, Sie beabsichtigen nicht, dass einer dieser Prozesse die MainPID ist.
  • Wenn ein Prozess fehlschlägt, systemdwird möglicherweise kein Fehlerstatus gemeldet. Es ist unklar, was mit den anderen Prozessen geschehen soll.

Empfehlung 1: Teilen Sie jeden Prozess in einen eigenen Dienst auf. Dann Type=simplewird es funktionieren. Auf diese Weise können Sie den Ausfall eines Dienstes erkennen und zuverlässig darauf zugreifen, ohne die anderen Bots zu beeinträchtigen.

Empfehlung 2: Fügen Sie hinzu Restart=on-failure. Dadurch kann ein ausgefallener Dienst automatisch neu gestartet werden (kein menschliches Eingreifen erforderlich).

Empfehlung 3: Rufen Sie nicht bash„which calls screenwhich calls“ auf python3. Rufen Sie einfach Python direkt auf. screenist ein Workaround, der in einer systemdUmgebung nicht notwendig ist.

Empfehlung 4: Um dies umzusetzen sleep 3, können Sie einExecStartPre=

Wenn Sie diese Empfehlungen befolgen, nyoko.servicewürde das folgendermaßen aussehen:

[Unit]
Description=Nyoko discord bot

[Service]
WorkingDirectory=/home/Nyoko
ExecStartPre=/usr/bin/sleep 3
ExecStart=/usr/bin/python3 /home/Nyoko/main.py
Restart=on-failure

[Install]
WantedBy=multi-user.target

Empfehlung 5: sleepist nicht sehr zuverlässig. An einem guten Tag verschwendet es 3 Sekunden. An einem schlechten Tag reicht es nicht aus und Ihr Dienst wird ausfallen. Erwägen Sie, After=lavalink.serviceIhrem [Unit]Abschnitt etwas hinzuzufügen, um sicherzustellen, lavalink.servicedass es vor etwas gestartet wird, das davon abhängt. Wenn lavalinkes eine Art Signal gibt, das anzeigt, dass es gestartet wurde (Datei wird erstellt oder Socket geöffnet), können Sie stattdessen darauf aufbauend auslösen.

verwandte Informationen