Schedulazione task ricorrenti con cron e crontab
Cron e anacron permettono la schedulazione di un task utente con una specifica ricorrenza, ad esempio giornaliera o mensile. Per la scrittura dei task da eseguire, ci si avvale di due programmi: crontab ed anacrontab.
Cron presume che il sistema sia attivo 24 ore su 24, quindi se in un certo periodo il computer è spento, i task schedulati in quel periodo non saranno eseguiti, e si dovrà attendere successiva ricorrenza schedulata affinché siano eseguiti. Ad esempio, se un task è schedulato per il primo giorno di ogni mese, ma il primo giorno di Giugno il computer è spento e sarà acceso solo il terzo giorno, allora i task non saranno eseguiti a Giugno, la successiva esecuzione avverrà il primo giorno di Luglio.
Gli utenti comuni non possono usare cron, però possono gestire i propri task attraverso crontab, se l’amministratore da loro i permessi di esecuzione del programma.
Anche gli amministratori possono utilizzare crontab, ed il corrispondente anacrontab, per gestire i task ricorrenti.
Configurazione di cron per l’amministratore
Per verificare lo stato del servizio cron, eseguire come utente root il comando:
systemctl status cron.service
Sia l’amministratore, sia le applicazioni di sistema possono inserire i propri task nelle directory:
/etc/cron.d/
/var/spool/cron
Gli amministratori possono comunque utilizzare crontab per gestire i task ricorrenti. I task vengono raccolti nel file:
/etc/crontab
Crontab
Per autorizzare gli utenti all’uso di crontab, creare (o modificare) il file /etc/cron.allow
(utente proprietario root
e gruppo proprietario crontab
) ed inserire una riga per ogni utente autorizzato.
Crontab si occupa di gestire il file in cui saranno indicati i task utente. Ogni file ha il nome dell’utente che ha schedulato i task.
Ogni utente abilitato ha il file dei task posizionato nella cartella:
/var/spool/cron/crontabs
Questo file deve essere modificato esclusivamente attraverso il comando crontab -e
, poiché questo comando verifica la sintassi del file e riavvia il demone cron.d
.
Ogni task eseguito prevede l’invio dell’output tramite una mail destinata all’utente. Le email sono memorizzate nella cartella:
/var/spool/mail/
Configurazione primo job con crontab
Per schedulare un nuovo task, sono necessari i seguenti step:
-
Selezionare l’editor per editare i task, aggiungendo al file
.profile
una riga in cui si specifica la variabile:export EDITOR="/usr/bin/micro"
-
Eseguire il comando:
crontab -e
-
Indicare le variabili
SHELL
,PATH
ed eventualmenteMAILTO
:SHELL=/bin/bash PATH=/usr/sbin:/usr/bin:/sbin:/bin:/root/bin:/bin MAILTO=root@example.com
-
Inserire l’espressione che indica l’intervallo di ripetizione (da https://crontab.guru/) seguito dal comando (percorso completo) da eseguire:
@reboot /bin/date "+\%F-\%T - Cron started" >> /home/io/login.txt 2>&1
Riavviando il sistema, l’utente dovrebbe trovare nella propria cartella /home/io
il file login.txt
con la data e l’ora di esecuzione del primo job schedulato.
Rilevare gli errori
Nel caso un task non sia eseguito, si può cercare una traccia di eventuali errori riferiti a cron nei file seguenti:
grep 'cron' /var/log/syslog
grep 'cron' /var/log/messages
I commenti non sono ammessi sulla stella linea di un comando o di una variabile, poiché vengono interpretati come parte del comando o della variabile.
Il carattere %
è interpretato come new line
, per poterlo utilizzare come carattere deve essere preceduto da un “escape” \
.
Dato che l’output di ogni task eseguito è salvato in una mail destinata all’utente, eventuali messaggi di errore possono venire salvati nelle mail. Per una ricerca di questi errori, visualizzare i file presenti nella cartella:
/var/spool/mail/
Sintassi di schedulazione di cron
La sintassi standard di una regola di cron è:
minuto ora giornoMese mese giornoSettimana job
minuto |
da 0 a 59 oppure * per indicare ogni minuto |
ora |
da 0 a 23 oppure * per indicare ogni ora |
giornoMese |
da 1 a 31 oppure * per indicare ogni giorno |
mese |
da 1 a 12 oppure * per indicare ogni mese |
giornoSettimana |
da 0 (Domenica) a 6 (Sabato) oppure * per indicare ogni giorno della settimana |
job |
il comando da eseguire |
Il campo giornoSettimana
va in OR logico con il campo giornoMese
, per cui il task viene eseguito sia nei giorni indicati dal campo giornoMese
, sia nei giorni indicati nel campo giornoSettimana
.
Se il task deve essere eseguito il giorno 30 di ogni mese, allora il task non sarà eseguito a Febbraio (non ha 30 giorni). Se l’orario di esecuzione è alle 2:30 di notte, allora il task non sarà eseguito nel giorno del passaggio dall’ora solare a quella legale (gli orologi avanzano di un’ora, dalle 2:00 alle 3:00).
In ogni campo si possono usare i seguenti modelli:
* |
qualsiasi valore per il campo |
A,B |
esecuzione del task quando ha valore A oppure B (non aggiungere il carattere spazio) |
A-B |
esecuzione del task quando ha valore tra A e B (estremi compresi, senza spazio) |
A/B |
esecuzione del task quando la divisione ha resto zero |
Invece di specificare i singoli campi, si possono utilizzare le seguenti espressioni non standard:
@yearly |
esecuzione del task annuale (non-standard) |
@annually |
esecuzione del task annuale (non-standard) |
@monthly |
esecuzione del task mensile (non-standard) |
@weekly |
esecuzione del task settimanale (non-standard) |
@daily |
esecuzione del task giornaliera (non-standard) |
@hourly |
esecuzione del task oraria (non-standard) |
@reboot |
esecuzione del task ad ogni riavvio (non-standard) |
Esempi di schedulazione
Per lanciare il comando ogni giorno:
@daily comando
Per lanciare il comando ogni giorno alle 7.30:
30 7 * * * comando
Per lanciare il comando il giorno 1 ed il giorno 16 dei mesi che vanno da aprile a ottobre:
26 * 1,16 4-10 * comando
Per lanciare il comando nei mesi che vanno da aprile a ottobre, il giorno 1 ed il giorno 16 ma anche il lunedì dei mesi predetti:
26 * 1,16 4-10 1 comando
Per lanciare il comando alla fine di ogni mese, dato che non c’è l’opzione, si può usare il giorno successivo, quindi il primo del mese, magari alle due di notte:
0 2 1 * * comando
Si vuole lanciare il comando ogni 5 minuti delle ore lavorative (9-18), ma solo un’ora si ed un’ora no. Ricordando che la regola A/B
viene eseguito solo quando il resto della divisione è zero, la si può sfruttare per specificare l’esecuzione nelle ore pari, dato che solo le ore pari hanno resto zero, per cui l’espressione 9-18/2
realizza quanto desiderato:
*/5 9-18/2 * * * comando
Redirezione output
Aggiungendo una redirezione, l’output del task finisce nel file di log, come con la regola:
@reboot /bin/date "+\%F-\%T - Cron started" >> /home/io/login.txt
E’ possibile redirezionare il log ed evitare che la mail venga inviata, con la regola:
@reboot /bin/date "+\%F-\%T - Cron started" >> /home/io/login.txt 2>&1
E’ possibile verificare il valore delle variabili con le redirezioni:
/bin/echo $PATH > /root/path.txt
/usr/bin/env > /root/allEvnVars.txt
Errori tipici
Tutti i comandi devono terminare con una nuova linea.
I caratteri speciali devono essere con escape (ad esempio il segno %
deve essere scritto \%
);
Esegui gli script tramite la shell corretta indicandola con:
#!/bin/bash
oppure con
/bin/bash -c "script.sh"
Se si hanno problemi di accesso o scrittura quando si esegue il comando crontab -e
, allora controllare i permessi:
Il comando crontab deve appartenere all’utente root:
# set owner, group and permission on the command "crontab"
chown root:crontab /usr/bin/crontab
chmod 2755 /usr/bin/crontab # set the permission to -rwxr-sr-x
La cartella /var/spool/cron/crontabs
deve appartenere a root
(permessi rwx
), al gruppo crontab
(permessi ws
) e deve avere lo sticky bit (il permesso di esecuzione) impostato per tutti gli altri utenti. Per comprendere i permessi, ricordare che T
=sticky bit senza permesso esecuzione, t
=sticky bit con permesso esecuzione.
# set owner, group and permission on the spool folders
chown root:crontab /var/spool/cron/crontabs
chmod 1730 /var/spool/cron/crontabs # set the permission to drwx-wx--T
Se si hanno problemi a rimuovere lo sticky bit, usare la sintassi simbolica “user meno S” o “others meno T”:
chmod u-s /var/spool/cron/crontabs
I file interni alla cartella /var/spool/cron/crontabs
devono appartenere ai rispettivi proprietari ed al gruppo crontab
e devono avere il permesso di lettura e scrittura rw
solo per il proprietario -rw-------
, nessun altro permesso (al gruppo o altri) deve essere impostato, altrimenti i task vengono eseguiti in modalità insicura (messaggio “INSECURE MODE (mode 0600 expected)”).
Riferimenti
How to use cron and anacron in Linux: Scheduling tasks with cron, crontab and anacron
Use systemd timers instead of cronjobs: Use systemd timers instead of cronjobs
Analyzing systemd calendar and timespans: Analyzing systemd calendar and timespans