253 lines
9.2 KiB
Markdown
253 lines
9.2 KiB
Markdown
---
|
||
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 <servizio>|Abilita il servizio all’avvio, che viene quindi attivato ogni qualvolta accedete
|
||
systemctl start <servizio>|Avvia immediatamente il servizio
|
||
systemctl restart <servizio>|Spegne e riavvia il servizio
|
||
systemctl stop <servizio>|Spegne il servizio, contrario di start
|
||
systemctl disable <servizio>|Disabilita il servizio, contrario di enable
|
||
systemctl status <servizio>|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)
|