Come creare e gestire le unità timer di Systemd

Crea, abilita, monitora e risolvi problemi delle unità timer di systemd con esempi pratici di `.timer`, `.service`, `systemctl` e `journalctl`.

Come Creare e Gestire Unità Timer di Systemd

Le unità timer di Systemd pianificano operazioni su Linux senza dipendere da cron. Se hai bisogno che il tuo server esegua un backup, un'operazione di pulizia, un controllo di integrità o un report a un orario prevedibile, un timer systemd ti offre pianificazione, isolamento del servizio, gestione delle dipendenze e log in un unico posto.

L'idea chiave è semplice: il file .timer dice quando eseguire, e il file .service dice cosa eseguire. Questa separazione rende i timer facili da ispezionare con systemctl e facili da debuggare con journalctl.

Comprendere la Struttura di un'Unità Timer di Systemd

Un'unità timer di systemd è sempre abbinata a una corrispondente unità di servizio (o altro tipo di unità) che deve attivare. L'unità timer stessa definisce quando l'unità associata deve essere attivata, mentre l'unità di servizio definisce quale azione eseguire. Entrambe le unità risiedono tipicamente nella stessa directory, spesso /etc/systemd/system/ per unità personalizzate.

Un file di unità timer tipico ha l'estensione .timer, e il suo file di unità di servizio associato ha l'estensione .service. Ad esempio, se vuoi pianificare un'attività definita in mytask.service, creerai un file mytask.timer.

Esempio: mytask.timer

[Unit]
Description=Esegue la mia attività personalizzata quotidianamente

[Timer]
OnCalendar=daily
Persistent=true

[Install]
WantedBy=timers.target

Analizziamo le sezioni chiave:

  • Sezione [Unit]:

    • Description: Una descrizione leggibile del timer. Utile per l'identificazione negli output di stato.
  • Sezione [Timer]: Questa è il cuore dell'unità timer, definisce la pianificazione.

    • OnCalendar=daily: Questa direttiva specifica quando il timer deve attivarsi. daily è una scorciatoia per mezzanotte di ogni giorno. Altri esempi includono:
      • hourly: Ogni ora.
      • weekly: Ogni settimana (equivalente a Mon *-*-* 00:00:00).
      • Sun *-*-* 10:00: Ogni domenica alle 10:00.
      • *-*-15 14:30: Il 15 di ogni mese alle 14:30.
      • Mon..Fri *-*-* 09:00: Nei giorni feriali alle 09:00.
    • Persistent=true: Se impostato su true, il timer si attiverà il prima possibile se l'evento si è verificato mentre il sistema era spento. Per i timer OnCalendar, significa che se il sistema era spento durante l'orario pianificato, il timer si attiverà una volta che il sistema si avvia e il timer diventa attivo.
    • OnBootSec=: Attiva il timer un tempo specificato dopo l'avvio del sistema. Ad esempio, OnBootSec=15min si attiverebbe 15 minuti dopo l'avvio.
    • OnUnitActiveSec=: Attiva il timer un tempo specificato dopo che l'unità che attiva è diventata attiva l'ultima volta. Ad esempio, OnUnitActiveSec=1h pianifica un'altra esecuzione un'ora dopo l'ultima attivazione del servizio associato.
    • OnUnitInactiveSec=: Attiva il timer un tempo specificato dopo che l'unità che attiva è diventata inattiva l'ultima volta.
    • AccuracySec=: Specifica la precisione del timer. Systemd cerca di riattivare il sistema per i timer solo se l'evento rientra in questa finestra temporale, aiutando a risparmiare energia. Il valore predefinito è 1min.
    • RandomizedDelaySec=: Aggiunge un ritardo casuale all'attivazione del timer, fino alla durata specificata. Utile per distribuire il carico.
  • Sezione [Install]: Questa sezione definisce come l'unità timer può essere abilitata.

    • WantedBy=timers.target: Questa direttiva assicura che quando il timer è abilitato, diventi parte di timers.target, che è un target standard che include tutti i timer attivi. Ciò significa che il timer si avvierà automaticamente all'avvio una volta abilitato.

Esempio: mytask.service

[Unit]
Description=Servizio per la mia attività personalizzata

[Service]
Type=oneshot
ExecStart=/usr/local/bin/my_custom_script.sh
User=myuser
Group=mygroup

[Install]
WantedBy=multi-user.target
  • Sezione [Unit]:

    • Description: Una descrizione del servizio.
  • Sezione [Service]: Questa definisce il servizio stesso.

    • Type=oneshot: Adatto per attività che vengono eseguite una volta e poi terminano. Esistono altri tipi per demoni a lunga esecuzione.
    • ExecStart: Il comando da eseguire. Assicurati che lo script abbia i permessi di esecuzione.
    • User/Group: Specifica l'utente e il gruppo sotto cui eseguire il comando. È buona pratica non eseguire attività come root a meno che non sia assolutamente necessario.
  • Sezione [Install]: Questa sezione di solito non è necessaria per un servizio oneshot che dovrebbe essere avviato solo da un timer. Abilita il timer, non il servizio.

Creare e Abilitare Unità Timer

Segui questi passaggi per creare e gestire le tue unità timer di systemd:

  1. Crea il File dell'Unità di Servizio: Definisci la tua attività in un file .service. Posizionalo in /etc/systemd/system/ (o ~/.config/systemd/user/ per timer specifici dell'utente).

    sudo nano /etc/systemd/system/mytask.service
    

    Incolla il contenuto dell'esempio del servizio sopra e salva.

  2. Crea il File dell'Unità Timer: Definisci la pianificazione in un file .timer corrispondente. Posizionalo nella stessa directory del file di servizio.

    sudo nano /etc/systemd/system/mytask.timer
    

    Incolla il contenuto dell'esempio del timer sopra e salva.

  3. Ricarica il Demone Systemd: Dopo aver creato o modificato i file delle unità, devi dire a systemd di ricaricare la sua configurazione.

    sudo systemctl daemon-reload
    
  4. Abilita il Timer: Per far sì che il timer si avvii automaticamente all'avvio, abilitalo.

    sudo systemctl enable mytask.timer
    

    Nota: NON abilitare il file di servizio se è destinato esclusivamente ad essere attivato dal timer.

  5. Avvia il Timer: Avvia il timer immediatamente. Successivamente verrà eseguito secondo la sua pianificazione.

    sudo systemctl start mytask.timer
    

Gestire e Monitorare le Unità Timer

Systemd fornisce diversi comandi systemctl per gestire e monitorare i tuoi timer:

  • Elenca tutti i timer: Visualizza tutti i timer attivi e inattivi.

    systemctl list-timers
    

    Questo comando fornisce un output come:

    NEXT                        LEFT        LAST        PASSED      UNIT          ACTIVATES
    Tue 2023-10-27 08:00:00 UTC 10h left    Wed 2023-10-26 08:00:00 UTC 14h ago       mytask.timer  mytask.service
    

    Questo mostra quando il timer è pianificato per essere eseguito la prossima volta, quanto tempo manca, quando è stato eseguito l'ultima volta e quale servizio attiva.

  • Elenca i timer per un'unità specifica: Se vuoi vedere i timer relativi a un servizio specifico.

    systemctl list-timers --all | grep mytask.service
    
  • Controlla lo Stato del Timer: Ottieni informazioni dettagliate su un timer specifico.

    systemctl status mytask.timer
    

    Questo mostrerà se il timer è attivo, quando è pianificato per essere eseguito la prossima volta e le voci di log recenti.

  • Visualizza i Log del Servizio: Per vedere l'output e lo stato dell'attività eseguita dal timer, controlla i log del servizio associato.

    journalctl -u mytask.service
    

    Puoi anche seguire i log in tempo reale:

    journalctl -f -u mytask.service
    
  • Ferma un Timer: Se hai bisogno di disabilitare temporaneamente un timer.

    sudo systemctl stop mytask.timer
    
  • Disabilita un Timer: Per impedire a un timer di avviarsi all'avvio e fermarlo se è in esecuzione.

    sudo systemctl disable --now mytask.timer
    

Configurazioni Avanzate dei Timer

Impostare Intervalli Specifici

Invece di daily o hourly, puoi definire intervalli più precisi:

  • Ogni N minuti: OnUnitActiveSec=15min (viene eseguito 15 minuti dopo l'ultima attivazione del servizio).
  • Orari specifici: OnCalendar=*-*-* 02:30:00 (viene eseguito quotidianamente alle 02:30).
  • Combinare condizioni: OnCalendar=Mon..Fri *-*-* 08:00:00 (viene eseguito nei giorni feriali alle 08:00).

Usare AccuracySec per il Risparmio Energetico

Se la tua attività non deve essere eseguita in un momento esatto, considera l'uso di AccuracySec. Ad esempio, AccuracySec=5min dice a systemd che va bene riattivare il sistema entro 5 minuti dall'orario pianificato. Ciò consente a systemd di raggruppare gli eventi del timer e potenzialmente mantenere il sistema in uno stato di basso consumo più a lungo.

[Timer]
OnCalendar=hourly
AccuracySec=5min

Persistent vs. WakeSystem

  • Persistent=true assicura che se un evento OnCalendar viene perso a causa dello spegnimento del sistema, verrà eseguito una volta al successivo avvio. Questo è cruciale per le attività che non devono essere saltate.
  • WakeSystem=true chiede a systemd di riattivare il sistema dalla sospensione per il timer, se il sistema e l'hardware lo supportano. Non è la stessa cosa di decidere se la macchina è alimentata a rete o a batteria.

Timer vs. Cron

Caratteristica Timer di Systemd Cron
Integrazione Integrazione profonda con servizi e target systemd Utility standalone
Pianificazione Flessibile (calendario, relativo, basato su avvio) Espressioni principalmente basate sul tempo
Logging Centralizzato tramite journalctl Sparsi (/var/log/syslog, /var/log/cron.log)
Gestione Errori Può collegare azioni a fallimenti del servizio Notifiche di base via email
Dipendenze Può dipendere da altri servizi attivi Limitato
Esecuzione Può essere eseguito come utenti e gruppi specifici Può essere eseguito come utenti specifici tramite crontab
Gestione Energia Può essere ottimizzato per il risparmio energetico (AccuracySec) Controllo meno diretto

Quando scegliere i Timer di Systemd:

  • Quando hai bisogno di una maggiore integrazione con altri servizi systemd.
  • Quando il logging centralizzato e un debugging più facile sono priorità.
  • Quando richiedi opzioni di pianificazione più avanzate (es. tempo dall'ultima esecuzione).
  • Per attività relative allo stato del sistema o alla gestione dell'energia.

Quando Cron potrebbe essere ancora preferito:

  • Per attività molto semplici e standalone su sistemi che non abbracciano completamente systemd.
  • Per la massima compatibilità tra diverse distribuzioni Linux e sistemi più vecchi.

Risoluzione dei Problemi Comuni

  • L'attività non viene eseguita:
    • Controlla lo stato del timer: systemctl status mytask.timer. Cerca messaggi Active: active e Triggered....
    • Controlla i log del servizio: journalctl -u mytask.service. Assicurati che lo script sia eseguibile e non abbia errori.
    • Verifica la sintassi di OnCalendar: Usa systemd-analyze calendar 'la-tua-stringa-calendario' per testare.
    • Assicurati che il timer sia abilitato e avviato: systemctl list-timers --all.
  • L'attività viene eseguita troppo presto/tardi:
    • Controlla AccuracySec e RandomizedDelaySec.
    • Assicurati che l'orologio di sistema sia accurato (timedatectl status).
  • Errori di permesso:
    • Conferma che l'User e il Group specificati nel file .service abbiano i permessi necessari per lo script e qualsiasi file a cui accede.
    • Se nessun utente è specificato, viene utilizzato root per impostazione predefinita. Fai attenzione con i privilegi di root.

Conclusione

Usa un timer systemd quando il lavoro appartiene al livello di servizio della macchina: backup, attività di pulizia, controlli di monitoraggio, hook per il rinnovo dei certificati e altre attività operative. Crea prima il servizio, poi crea il timer, esegui systemctl daemon-reload, abilita e avvia il timer, quindi verificalo con systemctl list-timers --all e journalctl -u tuo.servizio.