Astratto
Il codice corretto dovrebbe essere:
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Chiama questo script end_of_month.sh
e la chiamata in cron è semplicemente:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Ciò eseguirà lo script end_of_month
(che verificherà internamente che il giorno è l'ultimo giorno del mese) solo nei giorni 28, 29, 30 e 31. Non è necessario controllare la fine del mese in qualsiasi altro giorno.
Vecchio post.
Questa è una citazione dal libro "Linux Command Line and Shell Scripting Bible" di Richard Blum, Christine Bresnahan pp 442, Third Edition, John Wiley & Sons © 2015.
Sì, è quello che dice, ma è sbagliato / incompleto:
- Manca una chiusura
fi
.
- Ha bisogno di spazio tra
[
e il seguente `
.
- Si consiglia vivamente di utilizzare $ (...) invece di
`…`
.
- È importante usare virgolette intorno ad espansioni come
"$(…)"
- C'è un ulteriore
;
dopothen
Come lo so? (bene, per esperienza ☺) ma puoi provare Shellcheck . Incolla il codice dal libro (dopo gli asterischi) e ti mostrerà gli errori sopra elencati più uno "shebang mancante". Uno script senza errori in Shellcheck è questo:
#!/bin/sh
if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi
Quel sito funziona perché quello che è stato scritto è "codice shell". Questa è una sintassi che funziona in molte shell.
Alcuni problemi che la shellcheck non menziona sono:
Si presuppone che il comando date sia la versione della data GNU. Quello con -d
un'opzione che accetta tomorrow
come valore (busybox ha un'opzione -d ma non capisce domani e BSD ha -d
un'opzione ma non è correlato alla "visualizzazione" del tempo).
È meglio impostare il formato dopo tutte le opzioni date -d tomorrow +'%d'
.
L'ora di inizio cron è sempre in ora locale, il che può far iniziare un lavoro un'ora prima o dopo un giorno esatto se il DST (ora legale) è stato impostato o non impostato.
Quello che abbiamo fatto è uno script di shell che potrebbe essere chiamato con cron. Possiamo modificare ulteriormente lo script per accettare argomenti del programma o comando per eseguire, in questo modo (infine, il codice corretto):
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Chiama questo script end_of_month.sh
e la chiamata in cron è semplicemente:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Ciò eseguirà lo script end_of_month
(che verificherà internamente che il giorno è l'ultimo giorno del mese) solo nei giorni 28, 29, 30 e 31. Non è necessario controllare la fine del mese in qualsiasi altro giorno.
Assicurarsi che sia incluso il percorso corretto. Il PERCORSO all'interno di cron non sarà (probabilmente) uguale al PERCORSO dell'utente.
Si noti che esiste uno script di fine mese testato (come indicato di seguito) che potrebbe chiamare molte altre utilità o script.
Questo eviterà anche il problema aggiuntivo che cron genera con l'intera riga di comando:
- Cron divide la riga di comando su qualsiasi
%
anche se citato con '
o "
(funziona solo \
qui). Questo è un modo comune in cui i processi cron falliscono.
Puoi verificare se lo end_of_month.sh
script funziona correttamente in qualche data (senza attendere la fine del mese per scoprire che non funziona) testandolo con faketime:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....