systemd (Italiano)/Timers (Italiano)
I timer sono file unità di systemd il cui nome termina in .timer, utilizzati per controllare file .service o eventi. I timer possono essere usati come alternativa a cron (si veda #Come sostituto di cron). I timer dispongono di supporto integrato per eventi temporali di calendario, eventi temporali monotonici e possono essere eseguiti in modo asincrono.
Unità timer
I timer sono file unità di systemd con il suffisso .timer. I timer sono simili ad altri file di configurazione unità e vengono caricati dagli stessi percorsi, ma includono una sezione [Timer] che definisce quando e come il timer si attiva. I timer sono definiti secondo due tipologie:
-
Timer in tempo reale (anche detti wallclock timer) si attivano su un evento di calendario, allo stesso modo dei cronjob. Per definirli si usa l'opzione
OnCalendar=. -
Timer monotonici si attivano dopo un intervallo di tempo relativo a un punto di inizio variabile. Si interrompono se il computer viene temporaneamente messo in sospensione o spento. Esistono diversi timer monotonici, ma tutti hanno la forma:
OnTypeSec=. I timer monotonici comuni includonoOnBootSeceOnUnitActiveSec.
Per una spiegazione completa delle opzioni del timer, consultare systemd.timer(5). La sintassi degli argomenti per gli eventi di calendario e gli intervalli di tempo è definita in systemd.time(7).
timers.target che predispone tutti i timer che dovrebbero essere attivi dopo l'avvio (si veda systemd.special(7) per i dettagli). Per utilizzarlo, aggiungere WantedBy=timers.target alla sezione [Install] del proprio timer ed abilitare l'unità del timer.Unità di servizio
Per ogni file .timer, esiste un file .service corrispondente (ad esempio foo.timer e foo.service). Il file .timer attiva e controlla il file .service. Il file .service non richiede una sezione [Install] poiché sono le unità timer a essere abilitate. Se necessario, è possibile controllare un'unità con un nome diverso utilizzando l'opzione Unit= nella sezione [Timer] del timer.
Gestione
Per utilizzare un'unità timer, abilitarla e avviarla come qualsiasi altra unità (ricordando di aggiungere il suffisso .timer). Per visualizzare tutti i timer avviati, eseguire:
$ systemctl list-timers
NEXT LEFT LAST PASSED UNIT ACTIVATES Thu 2014-07-10 19:37:03 CEST 11h left Wed 2014-07-09 19:37:03 CEST 12h ago systemd-tmpfiles-clean.timer systemd-tmpfiles-clean.service Fri 2014-07-11 00:00:00 CEST 15h left Thu 2014-07-10 00:00:13 CEST 8h ago logrotate.timer logrotate.service
- Per elencare tutti i timer (compresi quelli inattivi), usare
systemctl list-timers --all. - Lo stato di un servizio avviato da un timer risulterà probabilmente inattivo, a meno che non sia attualmente in fase di attivazione.
- Se un timer non è più sincronizzato, può essere utile eliminare il suo file
stamp-*in/var/lib/systemd/timers(o~/.local/share/systemd/nel caso di timer utente). Si tratta di file di dimensione zero che indicano l'ultima volta che ogni timer è stato eseguito. Se eliminati, verranno ricostruiti al successivo avvio del relativo timer.
Esempi
Un file unità di servizio può essere pianificato con un timer in modo predefinito. Gli esempi che seguono pianificano l'esecuzione di foo.service tramite un timer corrispondente chiamato foo.timer.
Timer monotonico
Un timer che si avvia 15 minuti dopo l'avvio del sistema e successivamente ogni settimana finché il sistema è in funzione.
/etc/systemd/system/foo.timer
[Unit] Description=Esegue foo settimanalmente e all'avvio [Timer] OnBootSec=15min OnUnitActiveSec=1w [Install] WantedBy=timers.target
Timer in tempo reale
Un timer che si avvia una volta alla settimana (il lunedì a mezzanotte). Quando attivato, avvia immediatamente il servizio se l'ultimo orario di avvio è stato saltato (opzione Persistent=true), ad esempio a causa dello spegnimento del sistema:
/etc/systemd/system/foo.timer
[Unit] Description=Esegue foo settimanalmente [Timer] OnCalendar=weekly Persistent=true [Install] WantedBy=timers.target
Quando sono richiesti date e orari più specifici, gli eventi OnCalendar utilizzano il seguente formato:
GiornoDellaSettimana Anno-Mese-Giorno Ora:Minuto:Secondo
È possibile utilizzare un asterisco per specificare qualsiasi valore e le virgole per elencare i valori possibili. Due valori separati da .. indicano un intervallo contiguo.
Nell'esempio seguente il servizio viene eseguito i primi quattro giorni di ogni mese alle 12:00, ma solo se quel giorno è lunedì o martedì.
OnCalendar=Mon,Tue *-*-01..04 12:00:00
Per eseguire un servizio il primo sabato di ogni mese, usare:
OnCalendar=Sat *-*-1..7 18:00:00
Quando si usa la parte DayOfWeek, si deve specificare almeno un giorno feriale. Se si desidera che qualcosa venga eseguito ogni giorno alle 4 del mattino, usare:
OnCalendar=*-*-* 4:00:00
Per eseguire un servizio in orari diversi, OnCalendar può essere specificato più di una volta. Nell'esempio seguente, il servizio viene eseguito alle 22:30 nei giorni feriali e alle 20:00 nei fine settimana.
OnCalendar=Mon..Fri 22:30 OnCalendar=Sat,Sun 20:00
È inoltre possibile specificare un fuso orario alla fine della direttiva (usare timedatectl list-timezones per elencare i valori accettati)
OnCalendar=*-*-* 02:00:00 Europe/Rome
Ulteriori informazioni sono disponibili in systemd.time(7).
- Le specifiche temporali di
OnCalendarpossono essere testate per verificarne la validità e per calcolare la volta successiva in cui la condizione si verificherebbe, utilizzando l'opzionecalendardell'utility systemd-analyze. Ad esempio, si può usaresystemd-analyze calendar weeklyosystemd-analyze calendar "Mon,Tue *-*-01..04 12:00:00". Aggiungere--iterations=Nper richiedere la stampa di più iterazioni. - Il comando
faketimeè particolarmente utile per testare vari scenari con il comando precedente; è fornito dal pacchetto libfaketime. - Espressioni di eventi speciali come
dailyeweeklysi riferiscono a orari di avvio specifici e quindi tutti i timer che condividono tali eventi di calendario si avvieranno simultaneamente. I timer che condividono gli eventi di avvio possono causare scarse prestazioni del sistema se i servizi dei timer competono per le risorse di sistema. L'opzioneRandomizedDelaySecnella sezione[Timer]evita questo problema scaglionando casualmente l'orario di avvio di ciascun timer. Si veda systemd.timer(5). - Aggiungere l'opzione
AccuracySec=1usalla sezione[Timer]per evitare l'imprecisione del valore predefinito di 1m diAccuracySec. Si veda anche systemd.timer(5). - Alcune opzioni (
WakeSystem) potrebbero richiedere specifiche capacità del sistema e impedire l'avvio di un timer, causando i seguenti messaggi di errore: "Failed to enter waiting state: Operation not supported" e "Failed with result 'resources'.".
Unità timer transitorie
È possibile utilizzare systemd-run per creare unità .timer transitorie. In questo modo è possibile impostare un comando da eseguire a un orario specifico senza avere un file di servizio. Ad esempio, il seguente comando "tocca" un file dopo 30 secondi:
# systemd-run --on-active=30 /bin/touch /tmp/foo
È inoltre possibile specificare un file di servizio preesistente che non ha un file timer. Ad esempio, il comando seguente avvia l'unità systemd denominata someunit.service dopo che sono trascorse 12,5 ore:
# systemd-run --on-active="12h 30m" --unit someunit.service
Si veda systemd-run(1) per ulteriori informazioni ed esempi.
Come sostituto di cron
Sebbene cron sia probabilmente il pianificatore di compiti più noto, i timer di systemd possono rappresentare un'alternativa.
Vantaggi
I principali vantaggi dell'utilizzo dei timer derivano dal fatto che ogni compito ha il proprio servizio systemd. Alcuni di questi vantaggi sono:
- I compiti possono essere facilmente avviati indipendentemente dai loro timer. Questo semplifica il debugging.
- Ogni compito può essere configurato per essere eseguito in un ambiente specifico (si veda systemd.exec(5)).
- I compiti possono essere collegati ai cgroups.
- I compiti possono essere impostati per dipendere da altre unità di systemd.
- I compiti vengono registrati nel journal di systemd per facilitare il debugging.
Avvertenze
Alcune operazioni semplici da eseguire con cron risultano difficili con le sole unità timer:
- Creazione: per impostare un compito pianificato con systemd è necessario creare due file ed eseguire i comandi
systemctl, rispetto all'aggiunta di una singola riga a un crontab. - Email: non esiste un equivalente integrato a
MAILTOdi cron per l'invio di email in caso di fallimento del compito. Si veda systemd/Inviare notifiche via email per un esempio di configurazione di una funzionalità simile utilizzandoOnFailure=.
Si noti inoltre che le unità timer utente verranno eseguite solo durante una sessione di accesso utente attiva per impostazione predefinita. Tuttavia, il lingering può consentire ai servizi di essere eseguiti all'avvio anche quando l'utente non ha una sessione di accesso attiva.
Utilizzo di un crontab
Diverse avvertenze possono essere aggirate installando un pacchetto che analizza un crontab tradizionale per configurare i timer. systemd-cron-next-gitAUR e systemd-cronAUR sono due di questi pacchetti. Questi possono fornire la funzione MAILTO mancante.
Inoltre, come per i crontab, è possibile ottenere una visualizzazione unificata di tutti i compiti pianificati con systemctl. Si veda #Gestione.
Manualmente
Al di fuori della migrazione da un crontab esistente, potrebbe essere desiderabile utilizzare la stessa periodicità di cron. Per evitare il noioso compito di creare un timer per ogni servizio da avviare periodicamente, si utilizzi un'unità template, ad esempio:
/etc/systemd/system/monthly@.timer
[Unit] Description=Timer mensile per il servizio %i [Timer] OnCalendar=*-*-1 02:00:00 AccuracySec=6h RandomizedDelaySec=1h Persistent=true Unit=%i.service [Install] WantedBy=default.target
RandomizedDelaySec e non solo AccuracySec per evitare che tutte le unità avviate dal timer si attivino contemporaneamente.A questo punto è sufficiente abilitare e avviare monthly@nome_unit.timer.
monthly@btrfs-scrub@mnt-$(systemd-escape bbb76c63-e4ac-4e39-8897-a120c5d30686).timer.Trucchi e consigli
Gestione del "time to live"
Alcuni software tengono traccia del tempo trascorso dall'ultima esecuzione, ad esempio bloccando l'aggiornamento di un database se l'ultimo download è terminato meno di 24 ore fa.
Per impostazione predefinita, i timer non tengono traccia del momento in cui l'attività avviata è terminata. Per ovviare a questo problema, si può usare OnUnitInactiveSec:
/etc/systemd/system/daily-inactive@.timer
[Unit] Description=Avvia il servizio %i 24 ore dopo la sua disattivazione [Timer] OnUnitInactiveSec=1day1sec Unit=%i.service Persistent=true [Install] WantedBy=default.target
Restart=on-failure insieme a RestartSec, è possibile far rieseguire un'unità dopo un fallimento o un successo secondo pianificazioni diverse, si veda systemd.service(5) § OPTIONS.Notifiche desktop
systemd-timer-notifyAUR fornisce una notifica desktop automatica che aiuta l'utente a notare quando un servizio systemd viene attivato da un timer ed è in esecuzione. La notifica si chiuderà automaticamente al termine del servizio.
Questo può essere utile per capire perché l'utilizzo della CPU è elevato o per evitare uno spegnimento quando un servizio di backup non è terminato.
Per ulteriori dettagli e opzioni di configurazione, visitare https://gitlab.com/Zesko/systemd-timer-notify
Ulteriori risorse
- systemd.timer(5)
- Fedora:Features/SystemdCalendarTimers
- Gentoo:Systemd#Timer services
- systemd-cron — fornisce unità systemd per eseguire script cron; utilizza systemd-crontab-generator per convertire i crontab
- systemd-cron-next — strumento per generare timer/servizi da file crontab e anacrontab