Programme beim Serverstart automatisch ausführen (systemd und Cron)
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.
| Merkmal | systemd-Unit | Cron mit @reboot |
|---|---|---|
| Start beim Booten | ja | ja |
| Neustart nach Absturz | ja, automatisch | nein |
| Status abfragen | ja, per systemctl | nein |
| Protokoll der Ausgaben | ja, im Journal | nur wenn selbst umgeleitet |
| Startreihenfolge steuerbar | ja, etwa nach dem Netzwerk | nur 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 statusanzeigt. - 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=forkingund einePIDFile-Angabe. - User: Der Benutzer, unter dem der Dienst läuft. Lassen Sie Anwendungen nie unnötig als root laufen.
- WorkingDirectory: Ersetzt das
cdaus einem Startskript. - Restart=on-failure: systemd startet den Dienst nach einem Absturz neu. Mit
Restart=alwaysauch 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.shschreiben. - "Unit not found" nach dem Anlegen: Sie haben
systemctl daemon-reloadvergessen. - Der Dienst wird sofort wieder beendet: Das Programm verzweigt sich in den Hintergrund. Verwenden Sie
Type=forkingmit passenderPIDFile, 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 mitls -la. - Nach dem Booten läuft nichts: Der Dienst wurde gestartet, aber nicht aktiviert.
systemctl enableist 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?
Wo lege ich eine eigene systemd-Unit ab?
Mein Dienst läuft von Hand, startet aber nicht beim Booten. Warum?
Wie sehe ich die Ausgaben meines Dienstes?
Brauche ich für einen Gameserver noch screen oder tmux?
2024-2026 KernelHost GmbH. Alle Rechte vorbehalten. Diese Anleitung ist urheberrechtlich geschützt. Eine Veröffentlichung auf anderen Webseiten, auch auszugsweise oder in bearbeiteter Form, ist ohne unsere schriftliche Zustimmung nicht gestattet. Zitate mit Quellenangabe und Link sind ausdrücklich willkommen.

