Come eseguire uno script l’ultimo giorno del mese

Nella gestione di un server la possibilità di programmare l’esecuzione degli script è una funzione fondamentale, dato che permette di pianificare svariate attività senza la necessità di eseguirle a mano al momento richiesto.
In ambiente linux questo tipo di programmazione si ottiene tramite crontab che permette appunto di stabilire a che ora di che giorno dovrà essere eseguito uno script, anche con cadenza ripetitiva.
In poche parole, quindi, crontab permette di stabilire che un certo script verrà eseguito ogni mercoledì notte alle 3 in punto, o tutti i giorni lavorativi ogni 2 ore o ancora solo alla domenica tra le 14:00 e le 18:00.
Tutte funzioni particolarmente utili ed interessanti che però non prevedono almeno una situazione in cui mi sono imbattuto qualche tempo fa: la necessità di eseguire uno script l’ultimo giorno di ogni mese.

Programmare l'esecuzione di uno script per l'ultimo giorno di ogni mese
Non è cosa strana che certe operazioni si debbano svolgere appunto alla chiusura di un ciclo così specifico come il mese.
Il problema pratico nasce ovviamente dal fatto che i mesi non hanno tutti lo stesso numero di giorni e quindi non è semplicemente risolvibile tramite l’indicazione in crontab di eseguire l’attività il giorno 30 o 31.
Una soluzione semplice a questo tipo di esigenza è quella di pianificare l’esecuzione il primo giorno del mese (seguente).
Troppo facile. Mi è venuto in mente di trovare un modo affinchè l’operazione fosse effettivamente eseguita alla fine del mese. Ecco i risultati delle mie elucubrazioni.

Innanzitutto la possibilità di indicare il parametro “L”, che sta per “last” ovvero ultimo.
Usato nel campo del giorno della settimana permette l’esecuzione nell’ultimo giorno specificato di quel mese. Ad esempio “5L” corrisponde all’ultimo venerdì del mese, dato che 5 corrisponde a venerdì, nella settimana.
Usato nel campo del giorno del mese indica l’ultimo giorno del mese.
Perfetto ! Peccato che non tutte le versioni di cron lo supportino. Devi quindi verificare nella tua distribuzione se questa opzione è prevista. In quel caso il gioco è fatto, viceversa devi inventarti qualcosa d’altro.

Si può pensare allora ad un approccio un po’ più di tipo ‘brute force’ prendendo in considerazione tutte le possibilità e creando una pianificazione specifica.
In pratica prevedo una variante per ogni caso che si può verificare:

55 23 30 4,6,9,11                * job.sh
55 23 31 1,3,5,7,8,10,12  * job.sh
55 23 28 2                              * job.sh

In questo modo ho programmato lo stesso script in una modalità per i mesi di 30 giorni, in un’altra per quelli di 31, un’altra ancora per l’unico che ne 28.
Lo script viene eseguito alle 23:55 dell’ultimo giorno di ogni mese.
Non molto elegante, ma efficace.
Manca la variante per gli anni bisestili, in cui febbraio ha 29 giorni.
Giusto. In quel caso occorre intervenire a mano pianificando una variante una volta ogni 4 anni. Considerando la durata di un server (sia come hardware che come eventuale reinstallazione del sistema operativo) è una scomodità che si può anche accettare, ma di certo non siamo ancora alla soluzione definitiva e dotata di quell’eleganza formale a cui sempre tendiamo.

Mi è venuto in mente che si può tranquillamente giocare con le date, come del resto avevo già indicato in precedenza e usare un po’ di algebra. Ad esempio:

55 23 * * * [ `date -d tomorrow +%d` -eq ’01’ ] job.sh

Questo script è previsto per ogni fine giornata, alle 23:55 di tutti i giorni,
Ma viene verificata la situazione specifica in cui ci si trova e si controlla che il giorno seguente sia il giorno 1. Solo in quel caso lo script verrà eseguito.
In questo modo abbiamo programmato un solo script e vale per ogni condizione in cui ci si possa trovare.

3 comments

Lascia il tuo commento