Programma's automatisch starten bij de serverstart (systemd en cron)

Gepubliceerd op Bijgewerkt op 5 min leestijd

Zo starten toepassingen, gameservers en scripts na elke herstart vanzelf: met een systemd-service-unit als huidige standaard, of als alternatief via een cron-regel met @reboot.

Na elke herstart van de server alle diensten met de hand weer opstarten: dat kost tijd en gaat op een dag mis. Linux heeft daar een eigen mechanisme voor. In deze handleiding laten wij zien hoe u eigen toepassingen, gameservers, bots of scripts automatisch laat uitvoeren bij de serverstart.

Wij behandelen twee manieren: een systemd-service-unit als de tegenwoordig gebruikelijke oplossing en de oudere route via een cron-regel met @reboot. Beide werken los van de distributie en dus net zo goed op Debian, Ubuntu, AlmaLinux en Rocky Linux.

systemd of cron: welke aanpak past het best?

systemd is op alle actuele Linux-distributies de standaard voor diensten. Een cron-regel met @reboot start uw toepassing weliswaar ook, maar daar houdt het dan ook mee op.

Kenmerksystemd-unitcron met @reboot
Start bij het bootenjaja
Herstart na een crashja, automatischnee
Status opvragenja, via systemctlnee
Logboek van de uitvoerja, in het journalalleen als u zelf omleidt
Startvolgorde te sturenja, bijvoorbeeld na het netwerkalleen grofweg via sleep

Voor alles wat permanent moet draaien is de systemd-unit de betere keuze. De cron-regel blijft een snelle noodoplossing voor eenvoudige, eenmalige commando's.

Vereisten

  • Roottoegang tot uw VPS of rootserver via SSH.
  • Een startscript of programma dat op de commandoregel al netjes start. Test dat eerst met de hand, voordat u het automatiseert.
  • Het absolute pad naar dat script. Relatieve paden werken bij de systeemstart niet betrouwbaar.

Een systemd-service-unit aanmaken

Eigen units staan onder /etc/systemd/system/ en eindigen op .service. Maak het bestand aan:

nano /etc/systemd/system/mijndienst.service

Een eenvoudig raamwerk dat meteen bruikbaar is, ziet er zo uit:

[Unit]
Description=Mijn eigen dienst
After=network-online.target
Wants=network-online.target

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

[Install]
WantedBy=multi-user.target

Wat de afzonderlijke regels betekenen

  • Description: de naam in gewone taal die systemctl status toont.
  • After en Wants: de dienst start pas wanneer het netwerk beschikbaar is. Daarmee vervalt de truc met sleep die u van cron kent.
  • Type=simple: het programma blijft op de voorgrond draaien. Stuurt uw startscript zichzelf naar de achtergrond, dan heeft u in plaats daarvan Type=forking en een PIDFile-opgave nodig.
  • User: de gebruiker onder wie de dienst draait. Laat toepassingen nooit zonder noodzaak als root draaien.
  • WorkingDirectory: vervangt de cd uit een startscript.
  • Restart=on-failure: systemd start de dienst na een crash opnieuw. Met Restart=always gebeurt dat ook wanneer het programma zichzelf op de normale manier afsluit.
  • WantedBy=multi-user.target: zorgt ervoor dat de dienst bij de normale systeemstart meestart.

Dienst activeren en testen

Na elke wijziging aan een unit-bestand moet systemd het opnieuw inlezen. Daarna activeert u de dienst voor de systeemstart en start u hem meteen:

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

Of alles draait, ziet u met:

systemctl status mijndienst.service

De uitvoer van de toepassing belandt in het journal. Met het volgende commando leest u live mee, en dat is bij het opsporen van fouten de snelste weg:

journalctl -u mijndienst.service -f

Voor stoppen, opnieuw starten of permanent uitschakelen:

systemctl stop mijndienst.service
systemctl restart mijndienst.service
systemctl disable mijndienst.service

Voorbeeld: TeamSpeak 3-server automatisch starten

Het meegeleverde startscript van TeamSpeak stuurt zichzelf naar de achtergrond en maakt een PID-bestand aan. Daarom is hier Type=forking de juiste keuze:

[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

Pas de gebruikersnaam en de map aan uw eigen installatie aan. Belangrijk is dat de opgegeven gebruiker ook werkelijk eigenaar van de map is.

Voorbeeld: gameserver of bot via een startscript

Voor Minecraft, ARK, Arma 3, LinuxGSM-servers of een zelfgeschreven bot volstaat meestal de eenvoudige variant. De dienst draait op de voorgrond, systemd neemt bewaking en herstart voor zijn rekening:

[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

Wanneer meerdere diensten tegelijk starten en elkaar afremmen, spreidt u de start met verschillende waarden bij RestartSec, of vult u After= aan met de naam van de unit die als eerste moet draaien.

Alternatief: autostart via cron met @reboot

Wilt u bij het booten slechts één enkel commando uitvoeren en heeft u geen bewaking nodig, dan volstaat een cron-regel. Stel eerst de editor in en open de crontab:

export VISUAL=nano; crontab -e

Voeg daar een regel met @reboot toe:

@reboot sleep 60 && cd /<MAP-NAAR-SCRIPT>/ && bash <UW-SCRIPT>.sh

De @reboot zorgt ervoor dat het commando bij elke systeemstart één keer wordt uitgevoerd. Het deel sleep 60 wacht 60 seconden, zodat het netwerk en de database vooraf gereed zijn. Daarna wisselt het commando naar de map van uw script en start het daar.

Een voorbeeld voor een voiceserver die onder een eigen gebruiker moet draaien:

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

Voegt u meerdere regels toe, geef elke regel dan een andere sleep-waarde (minimaal 45), zodat niet alle diensten op hetzelfde moment starten. De waarde geeft u in seconden op.

Veelvoorkomende fouten

  • De dienst start niet, terwijl hij met de hand wel werkt: meestal ontbreekt een absoluut pad. In een unit of in cron is de omgevingsvariabele PATH zeer karig ingesteld, schrijf daarom altijd /bin/bash /volledig/pad/script.sh.
  • "Unit not found" na het aanmaken: u bent systemctl daemon-reload vergeten.
  • De dienst wordt meteen weer beëindigd: het programma stuurt zichzelf naar de achtergrond. Gebruik Type=forking met een passende PIDFile, of start het programma in voorgrondmodus.
  • Rechtenfouten bij de start: de bij User= opgegeven gebruiker mag de map niet benaderen. Controleer de eigenaar met ls -la.
  • Na het booten draait er niets: de dienst is wel gestart, maar niet geactiveerd. systemctl enable is de stap die hem permanent vastlegt.

Tot slot de beste test: start de server één keer opnieuw op met reboot en controleer daarna met systemctl status of alle diensten draaien zoals verwacht.

Veelgestelde vragen

Wat is beter: systemd of cron met @reboot?
Voor alles wat permanent moet draaien is systemd duidelijk de betere keuze. Het start de toepassing na een crash opnieuw op, toont de status en legt de uitvoer vast in het journal. Een cron-regel start het commando alleen één keer bij het booten.
Waar plaats ik een eigen systemd-unit?
Eigen unit-bestanden horen in /etc/systemd/system/ en eindigen op .service. Na elke wijziging moet u systemctl daemon-reload uitvoeren, anders kent systemd het bestand niet.
Mijn dienst draait met de hand, maar start niet bij het booten. Hoe komt dat?
Meestal ontbreekt een absoluut pad, omdat de omgevingsvariabele PATH bij de systeemstart zeer karig is ingesteld. De op één na meest voorkomende oorzaak: de dienst is wel gestart, maar nooit met systemctl enable permanent geactiveerd.
Hoe zie ik de uitvoer van mijn dienst?
systemd schrijft alles naar het journal. Met journalctl -u mijndienst.service -f leest u de uitvoer live mee, en dat is bij het opsporen van fouten de snelste weg.
Heb ik voor een gameserver nog screen of tmux nodig?
Nee. systemd houdt het proces zelf draaiende, legt de uitvoer vast in het journal en start het na een crash automatisch opnieuw op. Voor puur permanent draaien zijn screen en tmux daarmee overbodig.

Autostart systemd Crontab Linux Gameserver TeamSpeak3 Serverstart