Eseguire automaticamente i programmi all'avvio del server (systemd e cron)

Pubblicato il Aggiornato il 5 min di lettura

Applicazioni, game server e script che ripartono da soli dopo ogni riavvio: con un'unità di servizio systemd, lo standard di oggi, oppure con una voce cron @reboot.

Rimettere in piedi a mano tutti i servizi dopo ogni riavvio del server costa tempo e prima o poi qualcosa va storto. Linux porta con sé un meccanismo pensato proprio per questo. In questa guida ti mostriamo come far eseguire automaticamente all'avvio del server le tue applicazioni, i game server, i bot o i tuoi script.

Percorriamo due strade: un'unità di servizio systemd, la soluzione usuale oggi, e la via più datata di una voce cron con @reboot. Entrambe funzionano indipendentemente dalla distribuzione, quindi allo stesso modo su Debian, Ubuntu, AlmaLinux e Rocky Linux.

systemd o cron: quale strada fa al caso tuo?

systemd è lo standard per i servizi su tutte le distribuzioni Linux attuali. Anche una voce cron con @reboot avvia la tua applicazione, ma non sa fare nulla di più.

CaratteristicaUnità systemdCron con @reboot
Avvio al boot
Riavvio dopo un crashsì, automaticono
Verifica dello statosì, con systemctlno
Log degli outputsì, nel journalsolo se lo reindirizzi tu
Ordine di avvio controllabilesì, ad esempio dopo la retesolo in modo grossolano, con sleep

Per tutto ciò che deve restare in esecuzione in modo permanente, l'unità systemd è la scelta migliore. La voce cron resta un ripiego rapido, buono per semplici comandi da eseguire una volta sola.

Prerequisiti

  • Accesso root al tuo VPS o al tuo server root via SSH.
  • Uno script di avvio o un programma che si avvia già senza problemi dalla riga di comando. Provalo prima a mano, e solo dopo automatizzalo.
  • Il percorso assoluto di questo script. I percorsi relativi non funzionano in modo affidabile durante l'avvio del sistema.

Creare un'unità di servizio systemd

Le unità personali si trovano in /etc/systemd/system/ e terminano con .service. Crea il file:

nano /etc/systemd/system/mioservizio.service

Uno scheletro semplice e subito utilizzabile è questo:

[Unit]
Description=Il mio servizio
After=network-online.target
Wants=network-online.target

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

[Install]
WantedBy=multi-user.target

Che cosa significano le singole righe

  • Description: il nome in chiaro che systemctl status mostra.
  • After e Wants: il servizio parte solo quando la rete è disponibile. Così non serve più il trucco dello sleep che si conosce da cron.
  • Type=simple: il programma resta in esecuzione in primo piano. Se il tuo script di avvio passa da solo in background, ti servono invece Type=forking e una voce PIDFile.
  • User: l'utente con cui gira il servizio. Non far mai girare un'applicazione come root senza una vera necessità.
  • WorkingDirectory: sostituisce il cd di uno script di avvio.
  • Restart=on-failure: systemd riavvia il servizio dopo un crash. Con Restart=always lo riavvia anche quando il programma termina regolarmente.
  • WantedBy=multi-user.target: fa in modo che il servizio venga avviato insieme al normale avvio del sistema.

Attivare e testare il servizio

Dopo ogni modifica a un file di unità, systemd deve rileggerlo. Poi attivi il servizio per l'avvio del sistema e lo lanci subito:

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

Per vedere se tutto gira:

systemctl status mioservizio.service

Gli output dell'applicazione finiscono nel journal. Con il comando seguente li leggi in diretta, che è la via più rapida quando cerchi un errore:

journalctl -u mioservizio.service -f

Per fermare, riavviare o disattivare in modo permanente:

systemctl stop mioservizio.service
systemctl restart mioservizio.service
systemctl disable mioservizio.service

Esempio: avviare automaticamente un server TeamSpeak 3

Lo script di avvio fornito con TeamSpeak si manda da solo in background e crea un file PID. Per questo motivo qui la scelta corretta è Type=forking:

[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

Adatta nome utente e cartella alla tua installazione. È importante che l'utente indicato sia davvero il proprietario della cartella.

Esempio: game server o bot tramite script di avvio

Per Minecraft, ARK, Arma 3, i server LinuxGSM o un bot scritto da te basta di regola la variante semplice. Il servizio gira in primo piano e systemd si occupa del monitoraggio e del riavvio:

[Unit]
Description=Game server
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

Se più servizi partono nello stesso momento e si rallentano a vicenda, distribuisci l'avvio usando valori diversi per RestartSec oppure integra After= con il nome dell'unità che deve partire per prima.

Alternativa: avvio automatico con cron e @reboot

Se vuoi solo eseguire un singolo comando al boot e non ti serve alcun monitoraggio, basta una voce cron. Imposta prima l'editor, poi apri la crontab:

export VISUAL=nano; crontab -e

Inserisci lì una riga con @reboot:

@reboot sleep 60 && cd /<CARTELLA-DELLO-SCRIPT>/ && bash <TUO-SCRIPT>.sh

Il @reboot fa sì che il comando venga eseguito una volta a ogni avvio del sistema. La parte sleep 60 attende 60 secondi, in modo che rete e database siano pronti prima. Poi il comando entra nella cartella del tuo script e lo avvia.

Un esempio per un server vocale che deve girare con un utente dedicato:

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

Se inserisci più righe, dai a ognuna un valore sleep diverso (almeno 45), così i servizi non partono tutti nello stesso istante. Il valore si indica in secondi.

Errori frequenti

  • Il servizio non parte, anche se a mano funziona: di solito manca un percorso assoluto. Sia in un'unità sia in cron la variabile d'ambiente PATH è impostata in modo molto ridotto, quindi scrivi sempre /bin/bash /percorso/completo/script.sh.
  • "Unit not found" subito dopo aver creato il file: hai dimenticato systemctl daemon-reload.
  • Il servizio termina subito dopo l'avvio: il programma passa in background. Usa Type=forking con il PIDFile corrispondente, oppure avvia il programma in modalità primo piano.
  • Errori di permessi all'avvio: l'utente indicato in User= non può accedere alla cartella. Verifica il proprietario con ls -la.
  • Dopo il boot non gira nulla: il servizio è stato avviato, ma non attivato. systemctl enable è il passo che lo registra in modo permanente.

Per chiudere, il test migliore di tutti: riavvia una volta il server con reboot e controlla poi con systemctl status se tutti i servizi girano come previsto.

Domande frequenti

Meglio systemd o cron con @reboot?
Per tutto ciò che deve restare in esecuzione in modo permanente systemd è nettamente superiore. Riavvia l'applicazione dopo un crash, mostra lo stato e registra gli output nel log. Una voce cron si limita ad avviare il comando una sola volta al boot.
Dove metto la mia unità systemd?
I file di unità personali vanno in /etc/systemd/system/ e terminano con .service. Dopo ogni modifica devi eseguire systemctl daemon-reload, altrimenti systemd non conosce il file.
Il mio servizio funziona a mano, ma non parte al boot. Perché?
Di solito manca un percorso assoluto, perché all'avvio del sistema la variabile d'ambiente PATH è impostata in modo molto ridotto. Il secondo motivo più frequente: il servizio è stato solo avviato, ma mai attivato in modo permanente con systemctl enable.
Come vedo gli output del mio servizio?
systemd scrive tutto nel journal. Con journalctl -u mioservizio.service -f leggi gli output in diretta, che è la via più rapida quando cerchi un errore.
Per un game server mi servono ancora screen o tmux?
No. systemd tiene in vita il processo da solo, registra l'output e lo riavvia automaticamente dopo un crash. Per il semplice funzionamento continuo screen e tmux diventano quindi superflui.

Avvio automatico systemd Crontab Linux Game server TeamSpeak3 Avvio del server