Abstrait
Le code correct doit être:
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Appelez ce script end_of_month.sh
et l'appel en cron est simplement:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Cela exécuterait le script end_of_month
(qui vérifiera en interne que le jour est le dernier jour du mois) uniquement les jours 28, 29, 30 et 31. Il n'est pas nécessaire de vérifier la fin du mois un autre jour.
Ancien poste.
Il s'agit d'une citation tirée du livre «Linux Command Line and Shell Scripting Bible» de Richard Blum, Christine Bresnahan pp 442, troisième édition, John Wiley & Sons © 2015.
Oui, c'est ce qu'il dit, mais c'est faux / incomplet:
- Manque une fermeture
fi
.
- Besoin d'espace entre
[
les éléments suivants `
.
- Il est fortement recommandé d'utiliser $ (…) au lieu de
`…`
.
- Il est important que vous utilisiez des guillemets autour des extensions comme
"$(…)"
- Il y a un supplément
;
aprèsthen
Comment puis-je savoir? (enfin, par expérience ☺) mais vous pouvez essayer Shellcheck . Collez le code du livre (après les astérisques) et il vous montrera les erreurs listées ci-dessus plus un "shebang manquant". Voici un script sans erreur dans Shellcheck:
#!/bin/sh
if [ "$(date +%d -d tomorrow)" = 01 ] ; then script.sh; fi
Ce site fonctionne parce que ce qui a été écrit est du "code shell". C'est une syntaxe qui fonctionne dans de nombreux shells.
Certains problèmes que shellcheck ne mentionne pas sont:
Il suppose que la commande date est la version de date GNU. Celui avec une -d
option qui accepte tomorrow
comme valeur (busybox a une option -d mais ne comprend pas demain et BSD a une -d
option mais n'est pas liée à "l'affichage" de l'heure).
Il est préférable de définir le format après toutes les options date -d tomorrow +'%d'
.
L'heure de début cron est toujours en heure locale, ce qui peut faire démarrer une tâche 1 heure plus tôt ou plus tard qu'un compte de jour exact si l'heure d'été (DST) est réglée ou non.
Ce que nous avons fait, c'est un script shell qui pourrait être appelé avec cron. Nous pouvons encore modifier le script pour accepter les arguments du programme ou de la commande à exécuter, comme ceci (enfin, le code correct):
#!/bin/sh
[ "$#" -eq 0 ] && echo "Usage: $0 command [args]" && exit 1
[ "$(date -d tomorrow +'%d')" = 01 ] || exit 0
exec "$@"
Appelez ce script end_of_month.sh
et l'appel en cron est simplement:
00 12 28-31 * * /path/to/script/end_of_month.sh command
Cela exécuterait le script end_of_month
(qui vérifiera en interne que le jour est le dernier jour du mois) uniquement les jours 28, 29, 30 et 31. Il n'est pas nécessaire de vérifier la fin du mois un autre jour.
Assurez-vous que le chemin correct est inclus. Le PATH à l'intérieur de cron ne sera pas (probablement) le même que le PATH utilisateur.
Notez qu'il existe un script de fin de mois testé (comme indiqué ci-dessous) qui pourrait appeler de nombreux autres utilitaires ou scripts.
Cela évitera également le problème supplémentaire que cron génère avec la ligne de commande complète:
- Cron fractionne la ligne de commande sur n'importe quel
%
fichier même s'il est cité avec '
ou "
(seul un \
fonctionne ici). C'est une manière courante d'échouer dans les tâches cron.
Vous pouvez tester si le end_of_month.sh
script fonctionne correctement à une certaine date (sans attendre la fin du mois pour découvrir qu'il ne fonctionne pas) en le testant avec faketime:
$ faketime 2018/10/31 ./end_of_month echo "Command will be executed...."
Command will be executed....