Salta al contenuto principale

Orvieto Linux User Group | Promozione software libero a Orvieto

I Timer di systemd: guida pratica per automatizzare attività su Linux

Timer di systemd: guida pratica per automatizzare attività su Linux Eseguire automaticamente un backup, avviare uno script ogni notte, pulire una directory oppure eseguire periodicamente un’attività di manutenzione sono operazioni molto comuni in un sistema Linux. Tradizionalmente, uno degli strumenti più utilizzati per questo scopo è stato cron. systemd mette però a disposizione un meccanismo integrato nel proprio sistema di Unit: i Timer. Una Unit di tipo .timer permette di stabilire quando deve essere attivata un’altra Unit, normalmente un servizio .service. In questo modo è possibile costruire automazioni che utilizzano gli stessi strumenti che abbiamo già incontrato negli articoli precedenti: Unit, servizi, dipendenze, systemctl e journalctl. In questa guida vedremo cosa sono i Timer, come sono strutturati e come creare un semplice esempio funzionante. Cosa imparerai Al termine dell’articolo saprai: che cosa sono i Timer di systemd; perché un .timer lavora normalmente insieme a un .service; come eseguire un’attività dopo un determinato intervallo; come pianificare un’attività a un’ora specifica; come attivare e verificare un Timer; che cosa significa Persistent=true; quando può essere conveniente utilizzare un Timer al posto di cron. Che cos’è un Timer di systemd? Un Timer è una particolare Unit con estensione: .timer Il suo compito non è eseguire direttamente un comando, ma attivare un’altra Unit quando si verifica una determinata condizione temporale. Nella configurazione più comune avremo quindi due file: mio-task.service mio-task.timer Il primo contiene l’attività da eseguire. Il secondo stabilisce quando eseguirla. Per convenzione, quando un Timer si chiama backup.timer, systemd cerca automaticamente una Unit backup.service da attivare. È comunque possibile indicare esplicitamente un’altra Unit tramite Unit=. Possiamo quindi rappresentare il meccanismo in questo modo: TIMER │ │ quando? ▼ SERVICE │ │ cosa fare? ▼ COMANDO È una distinzione importante: il Timer decide quando eseguire qualcosa, mentre il Service descrive cosa deve essere eseguito. Il nostro primo esempio Realizziamo un esempio molto semplice: uno script che scrive la data e l’ora dell’esecuzione in un file di log. Creiamo lo script: sudo nano /usr/local/bin/systemd-timer-demo.sh Inseriamo: #!/bin/bash echo "Esecuzione: $(date)" >> /var/log/systemd-timer-demo.log Rendiamo eseguibile lo script: sudo chmod +x /usr/local/bin/systemd-timer-demo.sh Ora creiamo il relativo Service: sudo nano /etc/systemd/system/systemd-timer-demo.service Il contenuto sarà: [Unit] Description=Esempio di servizio attivato da un Timer systemd [Service] Type=oneshot ExecStart=/usr/local/bin/systemd-timer-demo.sh In questo caso utilizziamo: Type=oneshot perché il nostro programma viene eseguito, svolge il proprio compito e termina. Non abbiamo bisogno di un processo che rimanga continuamente in esecuzione. Creiamo il Timer Adesso possiamo creare la Unit che stabilirà quando eseguire il servizio: sudo nano /etc/systemd/system/systemd-timer-demo.timer Inseriamo: [Unit] Description=Esegue periodicamente il servizio di esempio [Timer] OnBootSec=5min OnUnitActiveSec=1h Persistent=true [Install] WantedBy=timers.target Abbiamo introdotto tre direttive importanti. OnBootSec= Stabilisce un intervallo relativo all’avvio del sistema. Nel nostro esempio: OnBootSec=5min significa che il Timer entrerà in azione cinque minuti dopo il boot. OnUnitActiveSec= Permette di definire un intervallo relativo all’ultima attivazione della Unit associata. Nel nostro esempio: OnUnitActiveSec=1h chiede di eseguire nuovamente il servizio a intervalli di un’ora. Persistent= Questa direttiva è particolarmente interessante. Con: Persistent=true systemd memorizza su disco l’ultima attivazione del Timer. Se il computer era spento nel momento in cui sarebbe dovuta avvenire un’esecuzione di un Timer basato su OnCalendar=, al successivo avvio systemd può eseguire l’attività persa. Questa opzione ha effetto sui Timer basati su calendario. Per questo motivo Persistent=true è molto utile, ad esempio, per attività di manutenzione o backup su macchine che possono rimanere spente. Ricaricare systemd e avviare il Timer Come abbiamo già visto quando abbiamo creato il nostro primo servizio, dopo aver aggiunto nuove Unit è necessario ricaricare la configurazione: sudo systemctl daemon-reload A questo punto possiamo attivare il Timer: sudo systemctl enable –now systemd-timer-demo.timer L’opzione –now permette di abilitarlo per l’avvio automatico e di avviarlo immediatamente. Possiamo verificare che sia attivo con: systemctl status systemd-timer-demo.timer Vedere tutti i Timer attivi Uno dei comandi più utili è: systemctl list-timers –all L’output contiene informazioni molto interessanti, tra cui: prossima esecuzione; tempo rimanente; ultima esecuzione; nome del Timer; servizio che verrà attivato.   È quindi uno dei primi comandi da utilizzare quando vogliamo capire se un’attività automatizzata è stata effettivamente pianificata. Pianificare un’attività a un’ora precisa con OnCalendar= I Timer diventano particolarmente interessanti quando utilizziamo: OnCalendar= Questa direttiva permette di utilizzare espressioni basate sul calendario. Ad esempio: OnCalendar=daily esegue l’attività quotidianamente. Possiamo anche specificare un orario: OnCalendar=*-*-* 03:00:00 In questo caso l’attività viene pianificata ogni giorno alle 03:00. Oppure possiamo utilizzare espressioni come: OnCalendar=weekly o: OnCalendar=monthly La sintassi di OnCalendar è molto più ricca e permette di descrivere date, giorni della settimana e orari in maniera estremamente flessibile. systemd mette inoltre a disposizione systemd-analyze calendar per verificare e normalizzare un’espressione prima di inserirla nel Timer. Ad esempio: systemd-analyze calendar "Mon *-*-* 03:00:00" è un ottimo modo per controllare quando verrà eseguita una determinata espressione. Un esempio più realistico: un backup giornaliero A questo punto possiamo sostituire il nostro semplice script con qualcosa di più utile. Immaginiamo di avere uno script: /usr/local/bin/backup.sh che esegue un backup con rsync. Il relativo Service potrebbe essere: [Unit] Description=Backup automatico [Service] Type=oneshot ExecStart=/usr/local/bin/backup.sh e il Timer: [Unit] Description=Backup giornaliero [Timer] OnCalendar=*-*-* 02:00:00 Persistent=true [Install] WantedBy=timers.target Il risultato è molto semplice da comprendere: systemd │ ▼ backup.timer │ ogni giorno alle 02:00 │ ▼ backup.service │ ▼ backup.sh │ ▼ rsync In questo modo abbiamo separato completamente la pianificazione dall’attività da eseguire. Ed è proprio questa separazione che rende i Timer di systemd molto flessibili. Timer di systemd o cron? Non significa che cron sia diventato inutile. Cron rimane uno strumento semplice, maturo e ancora molto utilizzato. I Timer di systemd hanno però un vantaggio importante: sono integrati direttamente nell’ecosistema systemd. Questo significa che possiamo utilizzare insieme: systemctl per amministrarli; journalctl per analizzarne i log; dipendenze tra Unit; Target; utenti e permessi; le numerose possibilità offerte dai Service.   Inoltre, systemctl list-timers permette di avere una visione centralizzata delle attività pianificate. Per un sistema già basato su systemd, quindi, un Timer rappresenta spesso una soluzione naturale per nuove automazioni. I comandi da ricordare | Operazione | Comando | | ———————— | —————————————- | | Elencare i Timer