Come eseguire uno script il primo mercoledì di ogni mese
Qualche giorno fa Pierluigi leggendo l’articolo Come eseguire uno script l’ultimo giorno del mese ha posto una domanda interessante: e se volessi eseguire lo script ogni primo mercoledi di ogni mese, alle ore 12 ?
La questione non è banale e richiede una risposta articolata, che prende spunto da quanto scritto nella pagina sopra indicata. Non torno sugli aspetti di base, che possono essere consultati lì, ma passo direttamente in medias res.
Non essendoci in cron la possibilità diretta di impostare una regola di questo tipo, una possibile soluzione è quella di inserire nello script da eseguire una valutazione sulla giornata attuale. La verifica della condizione se il giorno in corso è Mercoledì, con conseguente uscita diretta se è un qualsiasi altro giorno. Soluzione poco elegante e di difficile interpretazione da parte di altri in caso di manutenzione. Decido di cercare qualcosa di diverso.
In prima approssimazione il comando che mi viene spontaneo creare è il seguente
0 12 1-7 * 3 job.sh
0 = minuto 0
12 = ora 12
1-7 = giorni del mese da 1 a 7, considerando che il *primo* Mercoledì deve essere in questo intervallo
* = tutti i mesi
3 = giorno della settimana Mercoledì
job.sh = script da eseguire
Apparentemente ha una sua ragion d’essere, ma c’è qualcosa che non va. Infatti l’impostazione 1-7 non è alternativa all’indicazione del giorno 3 (Mercoledì). In altre parole causa l’esecuzione in ognuno di quei giorni e non solo il primo Mercoledì.
La soluzione corretta (perlomeno una che mi piace) è questa
0 12 * * 3 [ `date +\%d` -le 7 ] && job.sh
0 = minuto 0
12 = ora 12
* = qualunque giorno del mese
* = tutti i mesi
3 = giorno della settimana Mercoledì
[ `date +\%d` -le 7 ] &&
job.sh = script da eseguire
La magia avviene nella condizione [ `date +%d` -le 7 ] && della shell bash che restituisce un codice d’uscita basato sul fatto che la condizione sia vera o falsa. Se la condizione è vera si avrà l’esecuzione dello script, viceversa no. Inserendolo in crontab è necessario delimitare con backslash (\) il selettore %.
Ciò che stiamo facendo è una chiamata alla shell che valuta `date +%d`, ovvero esegue il comando date con l’attributo +%d, che restituisce il valore numerico di oggi, ad esempio 02.
Il resto della condizione -le 7 verifica se quel valore, il numero del giorno attuale, è minore o uguale a 7. Se è così, allora il giorno è nella prima settimana del mese, quindi viene restituito 1/vero, altrimenti il codice restituito è 0/falso e l’esecuzione viene fermata.
Quindi il comando viene eseguito da cron ogni settimana, di mercoledì, ma procede con il lancio dello script solo quando viene eseguito nei primi 7 giorni del mese.