--- class: post title: Systemd e gestione dei servizi date: "2023-04-16" layout: post author: piccihud published: false tags: - guide --- # Systemd e gestione dei servizi Systemd rappresenta uno degli strumenti di gestione centralizzata di init, demoni, librerie ed amministrazione del sistema più completo. Offre diversi tool per la gestione del sistema, come: - systemctl - journalctl - systemd-analyze - loginctl ## systemctl systemctl avvia i servizi e ha alcune funzioni per la gestione della sessione. ### I servizi I servizi, o demoni di sistema, sono software che per lo più girano di sottofondo generando e gestendo l’ambiente in cui l’utente e i programmi operano. Tutti i servizi si trovano in `/etc/systemd` e `/lib/systemd`. #### Attivare e disattivare i servizi Un servizio attivato è un servizio che si avvia con il sistema, per farlo: ```bash systemctl enable nomeservizio ``` Può essere poi disattivato con: ```bash systemctl disable nomeservizio ``` Una delle opzioni più utili è sicuramente enable --now: ```bash systemctl enable --now nomeservizio ``` che esegue enable e start in contemporanea #### Riepilogo | Comando | Spiegazione | |---------|-------------| systemctl enable |Abilita il servizio all’avvio, che viene quindi attivato ogni qualvolta accedete systemctl start |Avvia immediatamente il servizio systemctl restart |Spegne e riavvia il servizio systemctl stop |Spegne il servizio, contrario di start systemctl disable |Disabilita il servizio, contrario di enable systemctl status |Controlla lo stato del servizio, se è attivo, in errore o spento systemctl poweroff|Spegne il sistema systemctl reboot|Riavvia il sistema systemctl suspend|Sospende il sistema systemctl reboot --firmware-setup|È addirittura possibile riavviare direttamente su interfaccia EFI se disponibile: ### Scrivere un servizio I servizi si dividono in tre sezioni: - `Unit`, descrive il servizio, il modo in cui è avviato, i processi che dipendono da esso o quelli da cui dipende, il modo in cui si relaziona al sistema; - `Service`, descrive il comando o lo script eseguito, come viene eseguito, quante volte e quando considerarlo un fallimento; - `Install`, ulteriori specifiche su come il sistema deve abilitare il servizio, eventuali alias con cui collegarlo, quante unità attiva. Ogni sezione ha diverse opzioni disponibili. È possibile scrivere un servizio Systemd creando nella cartella `/etc/systemd/system` un file di estensione `.service` Questa la struttura base di un servizio: ```bash [Unit] Description=una descrizione del servizio After=lista di servizi che vengono eseguiti prima Before=lista di servizi che vengono dopo Condition....=se non verificata, il servizio non viene eseguito. Esistono vari tipi di condition, come ConditionHost, ConditionPathExist..etc [Service] Type=indica il tipo di servizio: simple, exec, forking, oneshot, dbus, notify o idle RemainAfterExit=true o false, indica se il processo deve rimanere in esecuzione anche dopo l'avvio del sistema ExecStart=lo script o il comando da eseguire. Lo script indicato nella sezione ExecStart deve essere eseguibile ExecStop=qui indicare ciò che viene eseguito quando viene terminato il processo Restart=indica se il processo deve essere eseguito più volte, ad esempio al successo, al fallimento, sempre... viene configurato con un timer, coi valori: no, on-success, on-failure, on-abnormal, on-abort, always... RestartSec=tempo prima del restart del servizio TimeoutStartSec=indica quanto tempo deve bloccare l'avvio prima di dire che un servizio è o non è fallito TimeoutStopSec=idem di sopra, ma in chiusura Standard....=StandardOutput e StandardError, cioè dove vengono stampati errori o messaggi. I valori possono essere: journal, tty, journal+console, file:/path/per/file (sarà cancellato se esiste), append:/path/per/file (aggiunge alla fine) [Install] WantedBy=indica la cartella in cui viene collegato il servizio ``` #### Servizio di avvio Un esempio di un servizio di avvio generico. Innanzitutto scrivere uno script che deve essere avviato ogni accensione, che sarà avviato con privilegi elevati (root). Poniamo ad esempio che il file sia: `/etc/avvio` È fondamentale che lo script sia eseguibile. Quindi creare il file `/etc/systemd/system/avvio.service` ```systemd [Unit] Description=Esegue /etc/avvio ConditionPathExists=/etc/avvio [Service] Type=oneshot ExecStart=/etc/avvio StandardOutput=journal [Install] WantedBy=multi-user.target ``` La sezione `[Unit]` fornisce una descrizione del servizio attraverso l’opzione `Description` e poi verifica che lo script da eseguire esista tramite `ConditionPathExist`. La parte `[Service]` informa che il servizio è oneshot. I servizi oneshot sono servizi di sistema che svolgono un'attività specifica e terminano al termine di tale attività. In altre parole, il processo è di breve durata. Lo `StandardOutput` dice dove saranno stampati i vari log. Nel caso dell'esempio nel journal. La parte `[Install]` dice che il file verrà eseguito nella cartella `multi-user` tramite opzione `WantedBy`. Nei sistemi GNU/Linux l’avvio è sottoposto a più fasi, dette livelli (**run level**): - livello 0: è il livello di spegnimento (poweroff), raggiunto quando il pc viene spento; - livello 1: livello di emergenza (rescue), è intermedio tra l’avvio del sistema hardware e quello software; - da livello 2 a livello 4: si parla di livelli utente (multi-user); - livello 5: è il livello grafico (graphic), usato dal display manager; - livello 6: è il livello di spegnimento o riavvio (reboot), in cui il sistema torna a livello 0 Il sistema dei livelli è stato ridefinito su systemd con i `target`. [Qui](https://www.freedesktop.org/software/systemd/man/systemd.special.html) maggiori informazioni sui target. A meno che non sia uno script abbastanza importante, è difficile vedere services con target diversi da multi-user.target. È ora possibile avvire il servizio e abilitarlo all'avvio coi comandi: ```bash systemctl start avvio.servizio systemctl enable avvio.service ``` #### systemd timer Ad ogni service si può associare un `timer`. Questa pratica potrebbe essere utile nel caso si volesse che un determinato script venisse ripetuto ogni settimana oppure ogni minuto piuttosto che ad ogni accesso. Associare al precedente servizio `avvio.service` un `avvio.timer` nella cartella `/etc/systemd/system`: ```bash [Unit] Description=un timer associato ad avvio.service [Timer] Unit=avvio.service OnUnitActiveSec=1us OnUnitInactiveSec=10s [Install] WantedBy=multi-user.target ``` Nella sezione `Timer` sono da inserire alcune informazioni: che unità far partire, quando il timer deve partire, ogni quanto il comando deve ripetersi. ```txt Unit=l'unità da avviare OnActiveSec=quanti secondi dopo l’avvio del timer OnBootSec=quanti secondi dopo l’avvio del pc OnStartupSec=quanti secondi dopo l’avvio di systemd (poco usato) OnUnitActiveSec=quanti secondi dopo l’attivazione dell’unità di riferimento OnUnitInactiveSec=quanti secondi dopo che l’unità diventa inattiva ``` Le unità di tempo impostabili sono: - us =microsecondo - ms =millisecondo - s =sec - m =minuto - h =ora - d =giorno - w =settimana - M =mese - y =anno I tempi di attivazione, se combinati, danno vita al tempo di ripetizione. Supponiamo di avere OnActiveSec=1us e OnUnitInactiveSec=10s, il timer una volta dato lo start da systemd si avvierebbe subito (1 microsecondo ), terminerebbe il job, e l’unità diventerebbe inattiva attivando il timer da 10s. È possibile avviare il timer in un giorno specifico con l'opzione: ```bash OnCalendar=valore in formato yyyy-MM-gg hh:mm:ss o simili ``` Per avviare un servizio tramite un timer, non va avviato il servizio, ma il timer stesso tramite il comando: ```bash systemctl start avvio.timer ``` #### Riavvio automatico di un servizio ```bash /etc/systemd/system/daemon.service [Unit] Description=Your Daemon Name StartLimitIntervalSec=300 StartLimitBurst=5 [Service] ExecStart=/path/to/executable Restart=on-failure RestartSec=1s [Install] WantedBy=multi-user.target ``` L'opzione `Restart` è impostata su `on-failure` così che il servizio venga riavviato se dovesse uscire con un *exit code* diverso da zero, oppure se terminato. L'opzione `RestartSec` configura il tempo necessario da attendere prima di riavviare il servizio. Altre due opzioni utili sono `StartLimitIntervalSec` e `StartLimitBurst`. Entrambe sono utili per la configurazione di quando Systemd dovrebbe smettere di provare a riavviare un servizio. Dopo aver aggiornato il file dell'unità di sistema, assicurarsi di eseguire il comando seguente affinché le modifiche abbiano effetto: ```bash sudo systemctl daemon-reload ``` ## Collegamenti - [https://linuxhub.it/articles/howto-usare-e-comprendere-systemd/](https://linuxhub.it/articles/howto-usare-e-comprendere-systemd/) - [https://linuxhub.it/articles/howto-creare-un-servizio-o-un-timer-di-systemd/](https://linuxhub.it/articles/howto-creare-un-servizio-o-un-timer-di-systemd/) - [https://freshman.tech/snippets/linux/auto-restart-systemd-service/](https://freshman.tech/snippets/linux/auto-restart-systemd-service/) - [https://www.baeldung.com/linux/systemd-service-periodic-restart](https://www.baeldung.com/linux/systemd-service-periodic-restart)