Programme beim Serverstart automatisch ausführen (systemd und Cron)

Veröffentlicht am Aktualisiert am 5 Min. Lesezeit

So starten Anwendungen, Gameserver und Skripte nach jedem Neustart von selbst: mit einer systemd-Service-Unit als heutigem Standard oder alternativ über einen Cron-Eintrag mit @reboot.

Nach jedem Neustart des Servers alle Dienste von Hand wieder hochfahren: das kostet Zeit und geht irgendwann schief. Linux bringt dafür einen eigenen Mechanismus mit. In dieser Anleitung zeigen wir, wie Sie eigene Anwendungen, Gameserver, Bots oder Skripte beim Serverstart automatisch ausführen lassen.

Wir gehen dabei zwei Wege durch: eine systemd-Service-Unit als heute übliche Lösung und den älteren Weg über einen Cron-Eintrag mit @reboot. Beide funktionieren unabhängig von der Distribution, also auf Debian, Ubuntu, AlmaLinux und Rocky Linux gleichermaßen.

systemd oder Cron: welcher Weg passt?

systemd ist auf allen aktuellen Linux-Distributionen der Standard für Dienste. Ein Cron-Eintrag mit @reboot startet Ihre Anwendung zwar ebenfalls, kann aber nicht mehr als das.

Merkmalsystemd-UnitCron mit @reboot
Start beim Bootenjaja
Neustart nach Absturzja, automatischnein
Status abfragenja, per systemctlnein
Protokoll der Ausgabenja, im Journalnur wenn selbst umgeleitet
Startreihenfolge steuerbarja, etwa nach dem Netzwerknur grob über sleep

Für alles, was dauerhaft laufen soll, ist die systemd-Unit die bessere Wahl. Der Cron-Eintrag bleibt eine schnelle Notlösung für einfache Einmalbefehle.

Voraussetzungen

  • Root-Zugriff auf Ihren vServer oder Rootserver über SSH.
  • Ein Startskript oder Programm, das sich auf der Kommandozeile bereits sauber starten lässt. Testen Sie das zuerst von Hand, bevor Sie es automatisieren.
  • Der absolute Pfad zu diesem Skript. Relative Pfade funktionieren beim Systemstart nicht zuverlässig.

Eine systemd-Service-Unit anlegen

Eigene Units liegen unter /etc/systemd/system/ und enden auf .service. Legen Sie die Datei an:

nano /etc/systemd/system/meinedienst.service

Ein einfaches, sofort einsatzbereites Grundgerüst sieht so aus:

[Unit]
Description=Mein eigener Dienst
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=meinbenutzer
WorkingDirectory=/opt/meinedienst
ExecStart=/bin/bash /opt/meinedienst/start.sh
Restart=on-failure
RestartSec=10

[Install]
WantedBy=multi-user.target

Was die einzelnen Zeilen bedeuten

  • Description: Klartextname, den systemctl status anzeigt.
  • After und Wants: Der Dienst startet erst, wenn das Netzwerk verfügbar ist. Damit entfällt der Trick mit sleep, den man aus Cron kennt.
  • Type=simple: Das Programm bleibt im Vordergrund laufen. Verzweigt sich Ihr Startskript selbst in den Hintergrund, brauchen Sie stattdessen Type=forking und eine PIDFile-Angabe.
  • User: Der Benutzer, unter dem der Dienst läuft. Lassen Sie Anwendungen nie unnötig als root laufen.
  • WorkingDirectory: Ersetzt das cd aus einem Startskript.
  • Restart=on-failure: systemd startet den Dienst nach einem Absturz neu. Mit Restart=always auch dann, wenn sich das Programm regulär beendet.
  • WantedBy=multi-user.target: Sorgt dafür, dass der Dienst beim normalen Systemstart mitgestartet wird.

Dienst aktivieren und testen

Nach jeder Änderung an einer Unit-Datei muss systemd sie neu einlesen. Anschließend aktivieren Sie den Dienst für den Systemstart und starten ihn direkt:

systemctl daemon-reload
systemctl enable --now meinedienst.service

Ob alles läuft, zeigt Ihnen:

systemctl status meinedienst.service

Die Ausgaben der Anwendung landen im Journal. Mit folgendem Befehl lesen Sie sie live mit, was bei der Fehlersuche der schnellste Weg ist:

journalctl -u meinedienst.service -f

Zum Stoppen, Neustarten oder dauerhaften Deaktivieren:

systemctl stop meinedienst.service
systemctl restart meinedienst.service
systemctl disable meinedienst.service

Beispiel: TeamSpeak-3-Server automatisch starten

Das mitgelieferte Startskript von TeamSpeak schickt sich selbst in den Hintergrund und legt eine PID-Datei an. Deshalb ist hier Type=forking richtig:

[Unit]
Description=TeamSpeak 3 Server
After=network-online.target
Wants=network-online.target

[Service]
Type=forking
User=teamspeak
WorkingDirectory=/home/teamspeak
ExecStart=/home/teamspeak/ts3server_startscript.sh start
ExecStop=/home/teamspeak/ts3server_startscript.sh stop
PIDFile=/home/teamspeak/ts3server.pid
Restart=on-failure
RestartSec=15

[Install]
WantedBy=multi-user.target

Passen Sie Benutzername und Verzeichnis an Ihre Installation an. Wichtig ist, dass der angegebene Benutzer dem Verzeichnis auch wirklich gehört.

Beispiel: Gameserver oder Bot per Startskript

Für Minecraft, ARK, Arma 3, LinuxGSM-Server oder einen selbst geschriebenen Bot genügt in der Regel die einfache Variante. Der Dienst läuft im Vordergrund, systemd übernimmt Überwachung und Neustart:

[Unit]
Description=Gameserver
After=network-online.target
Wants=network-online.target

[Service]
Type=simple
User=gameserver
WorkingDirectory=/home/gameserver/server
ExecStart=/bin/bash /home/gameserver/server/start.sh
Restart=always
RestartSec=15

[Install]
WantedBy=multi-user.target

Wenn mehrere Dienste gleichzeitig starten und sich gegenseitig ausbremsen, verteilen Sie den Start über unterschiedliche Werte bei RestartSec oder ergänzen Sie After= mit dem Namen der Unit, die zuerst laufen soll.

Alternative: Autostart über Cron mit @reboot

Wenn Sie nur einen einzelnen Befehl beim Booten ausführen möchten und keine Überwachung brauchen, reicht ein Cron-Eintrag. Stellen Sie zuerst den Editor ein und öffnen Sie die Crontab:

export VISUAL=nano; crontab -e

Tragen Sie dort eine Zeile mit @reboot ein:

@reboot sleep 60 && cd /<VERZEICHNIS-ZUM-SKRIPT>/ && bash <IHR-SKRIPT>.sh

Das @reboot sorgt dafür, dass der Befehl bei jedem Systemstart einmal ausgeführt wird. Der Teil sleep 60 wartet 60 Sekunden, damit Netzwerk und Datenbank vorher bereit sind. Danach wechselt der Befehl in das Verzeichnis Ihres Skripts und startet es.

Ein Beispiel für einen Voiceserver, der unter einem eigenen Benutzer laufen soll:

@reboot sleep 45 && cd /home/<TEAMSPEAK-VERZEICHNIS>/ && sudo -u <TEAMSPEAK-USER> bash ts3server_startscript.sh start

Wenn Sie mehrere Zeilen eintragen, geben Sie jeder einen anderen sleep-Wert (mindestens 45), damit nicht alle Dienste gleichzeitig starten. Der Wert wird in Sekunden angegeben.

Häufige Fehler

  • Der Dienst startet nicht, obwohl er von Hand funktioniert: Meist fehlt ein absoluter Pfad. In einer Unit oder in Cron ist die Umgebungsvariable PATH sehr knapp gesetzt, deshalb immer /bin/bash /voller/pfad/skript.sh schreiben.
  • "Unit not found" nach dem Anlegen: Sie haben systemctl daemon-reload vergessen.
  • Der Dienst wird sofort wieder beendet: Das Programm verzweigt sich in den Hintergrund. Verwenden Sie Type=forking mit passender PIDFile, oder starten Sie das Programm im Vordergrundmodus.
  • Rechtefehler beim Start: Der bei User= angegebene Benutzer darf nicht auf das Verzeichnis zugreifen. Prüfen Sie den Eigentümer mit ls -la.
  • Nach dem Booten läuft nichts: Der Dienst wurde gestartet, aber nicht aktiviert. systemctl enable ist der Schritt, der ihn dauerhaft einträgt.

Zum Abschluss der beste Test: Starten Sie den Server einmal mit reboot neu und prüfen Sie danach mit systemctl status, ob alle Dienste wie erwartet laufen.

Häufige Fragen

Was ist besser: systemd oder Cron mit @reboot?
Für alles, was dauerhaft laufen soll, ist systemd klar überlegen. Es startet die Anwendung nach einem Absturz neu, zeigt den Status an und protokolliert die Ausgaben. Ein Cron-Eintrag startet den Befehl nur einmal beim Booten.
Wo lege ich eine eigene systemd-Unit ab?
Eigene Unit-Dateien gehören nach /etc/systemd/system/ und enden auf .service. Nach jeder Änderung müssen Sie systemctl daemon-reload ausführen, sonst kennt systemd die Datei nicht.
Mein Dienst läuft von Hand, startet aber nicht beim Booten. Warum?
Meist fehlt ein absoluter Pfad, weil die Umgebungsvariable PATH beim Systemstart sehr knapp gesetzt ist. Der zweithäufigste Grund: Der Dienst wurde nur gestartet, aber nie mit systemctl enable dauerhaft aktiviert.
Wie sehe ich die Ausgaben meines Dienstes?
systemd schreibt alles ins Journal. Mit journalctl -u meinedienst.service -f lesen Sie die Ausgaben live mit, was bei der Fehlersuche der schnellste Weg ist.
Brauche ich für einen Gameserver noch screen oder tmux?
Nein. systemd hält den Prozess selbst am Laufen, protokolliert die Ausgabe und startet ihn nach einem Absturz automatisch neu. Für den reinen Dauerbetrieb sind screen und tmux damit überflüssig.

Autostart systemd Crontab Linux Gameserver TeamSpeak3 Serverstart