Exécuter une tâche cron le premier lundi de chaque mois?

32

Je voudrais exécuter un travail à partir de cron à 8h30 le premier lundi de chaque mois. La page Wikipedia cron dit

Alors que normalement le travail est exécuté lorsque les champs de spécification d'heure / date correspondent tous à l'heure et à la date actuelles, il y a une exception: si les deux "jour du mois" et "jour de la semaine" sont restreints (pas "*"), alors soit le champ "jour du mois" (3) ou le champ "jour de la semaine" (5) doit correspondre au jour en cours.

(mon accent)

Est-ce à dire que je ne peux pas faire le premier lundi du mois, je peux seulement faire le premier (ou autre) jour du mois? Je ne vois pas de solution.

Max Williams
la source
slhck - cela semble être une bonne solution - cela vous dérangerait-il de l'étendre en une réponse avec le code complet? alors je vais le marquer comme correct :)
Max Williams

Réponses:

39

Vous pouvez mettre la condition dans la commande crontab réelle:

[ "$(date '+%a')" = "Mon" ] && echo "It's Monday"

Maintenant, si cette condition est vraie l'un des sept premiers jours d'un mois, vous avez son premier lundi. Notez que dans la crontab, la syntaxe en pourcentage doit être échappée cependant:

0   12  1-7 *   *   [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday"

Remplacez la echocommande par la commande réelle que vous souhaitez exécuter. J'ai également trouvé une approche similaire .

slhck
la source
en fait, slhck, j'ai parlé trop tôt - cela ne fonctionne pas dans mon crontab: il semble avoir un problème avec le test de date pour une raison quelconque. Cela fonctionne dans la ligne de commande [ "$(date '+%a')" = "Mon" ] && echo "It's Monday"comme le fait [ $(date '+%a') = "Mon" ] && echo "It's Monday" Mais, dans la crontab, il semble échouer à ce test. Je ne peux pas non plus obtenir de commentaires utiles de cron: j'essaie [ "$(date '+%a')" = "Tue" ] >> /home/deploy/cron.log 2>&1de capturer toute sortie d'erreur dans un journal, mais cela ne fonctionne pas non plus: /
Max Williams
Hm. Pouvez-vous vérifier si la datesortie est correcte? Par exemple, laissez simplement une croncommande s'exécuter qui produit cela dans un fichier: date '+%a' > ~/datetest 2>&1- puis vérifiez si cela a abouti à la bonne chaîne de comparaison.
slhck
1
J'ai trouvé le problème - le pour cent en +%abesoin échapper quand il était dans la crontab, à savoir la ligne devait être celle - ci: [ "$(date '+\%a')" = "Mon" ] && echo "It's Monday". Si vous pouviez mettre à jour votre réponse, cela serait utile aux futurs lecteurs :) Merci encore - max
Max Williams
Oh, maintenant je vois pourquoi. Heureux que cela fonctionne maintenant, merci de l'avoir essayé!
slhck
15

J'ai un ordinateur avec des paramètres régionaux en espagnol, donc cette approche ne fonctionne pas pour moi car mon passe à lun

D'autres langues échoueraient également, alors j'ai fait une légère variation sur la réponse acceptée qui supprime la barrière linguistique:

 0 9 1-7 * *   [ "$(date '+\%u')" = "1" ] && echo "¡Es lunes!"
cumanacr
la source
+1 ¡Muy bien, señor!
JakeGould
1
Gracias ¡Pura vida! ; D
cumanacr
Ce devrait être la réponse acceptée. J'ai une locale néerlandaise qui utilise également des noms différents pour les jours de la semaine. Et utiliser des chiffres semble également plus propre que de comparer des chaînes pour déterminer le jour de la semaine.
0ne_Up
7

Je trouve cela plus facile lorsqu'il n'est pas nécessaire de gérer les numéros de jour.

Exécuter le premier lundi du mois:

0 2 * * 1 [ `date '+\%m'` == `date '+\%m' -d "1 week ago"` ] || /path/to/command

c'est-à-dire si le mois 1 il y a une semaine n'est pas le même que le mois en cours alors nous sommes le 1er jour 1 (= lundi) du mois.

De même, pour le troisième vendredi

0 2 * * 6 [ `date '+\%m'` == `date '+\%m' -d "3 weeks ago"` ] || /path/to/command

c'est-à-dire si le mois il y a 3 semaines est différent du mois en cours alors nous sommes le 3ème jour 6 (= vendredi) du mois

joel
la source
Le jour 6 de la semaine est le samedi et non le vendredi.
Robert
4

J'ai planifié un travail à exécuter le 4e lundi de chaque mois à 16h00 comme suit:

0 16 22-28 * Mon [ "$(date '+\%a')" == "Mon" ] && touch /home/me/FourthMonOfMonth.txt
Abhijit Mapgaonkar
la source
1

Pour autant que je sache, il n'est PAS possible d'utiliser uniquement crontab, mais on peut utiliser une fonction wrapper pour choisir le jour correct à partir d'une entrée de contab "sept premiers jours du mois"; voir cela de l'entrée.

Le script wrapper serait

#! /usr/bin/ksh
day=$(date +%d)
if ((day <= 7)) ; then
   exec somecommand
fi
exit 1

et vous devrez l'exécuter (en supposant qu'il s'appelle wrapper.sh et qu'il soit disponible dans le monde entier) en utilisant l'entrée crontab

0 0 * * 1 wrapper.sh
elemakil
la source
merci elemaki. J'ai pensé à une solution similaire en utilisant du code supplémentaire dans la tâche qui s'exécute, en lui faisant tester si c'est le premier lundi du mois dans le script, puis en l'appelant tous les lundis dans crontab. C'est un script rubis donc il est facile de tester le jour de la semaine. Mais j'espérais qu'il y aurait un seul moyen de crontab.
Max Williams
1

Sur Solaris 10, j'ai dû formater la condition comme suit:

[ `date +\%a` = "Sat" ] && echo "It's Saturday"
Volonté
la source
1

Vous pouvez essayer d'exécuter cronjob pendant les sept premiers jours du mois et ne l'exécuter que le lundi.

30 8 * * 1 [`date +\%d` -le 07] && <job>

Ci-dessus devrait fonctionner pour vous.

simer
la source
+1 succès de plus atteint la ration puis s'exécute pour la première semaine et vérifie lundi. :-)
xmedeko
1

Je recommande d'utiliser

"$(/bin/date '+%\w')" = "1"

au lieu de

"$(date '+\%a')" = "Mon"

pour éviter les problèmes de localisation.

Manus Freedom
la source
0

J'ai fait une solution générale pour ce genre de problèmes, ça marche pour les premier, deuxième, troisième ..... dernier jour de semaine du mois.

Vous pouvez l'utiliser comme ceci:

30 06 * * Mon run-if-today 1 "Mon" && echo "First Monday"
30 06 * * Thu run-if-today 3 "Thu" && echo "Third Thursday"
30 06 * * Sun run-if-today L "Sun" && echo "Last Sunday"

Le script run-if-today vérifie à la fois le jour de la semaine et la plage de dates de la semaine souhaitée, si les deux correspondent, il renvoie 0, sinon 1.

Vérifiez le code ici. https://github.com/xr09/cron-last-sunday

MGP
la source
0

Je crois que cela résout le problème plus élégamment:

30 8 1-7 * 1 /run/your/job.sh
symcbean
la source
1
Ah! : "Si les deux champs sont restreints (c'est-à-dire ne le sont pas *), la commande sera exécutée lorsque l'un des champs correspond à l'heure actuelle."
symcbean
Également en février (celui qui se termine le 28), il ne sera pas exécuté tous les 4 ans.
igraczech
"soit" signifie n'importe lequel d'entre eux, pas "les deux". cela se déroulera tous les jours pendant les 7 premiers jours du mois.
minusf
Cette ligne exécuterait une commande du premier au septième de chaque mois, ainsi que tous les lundis
Tomasz Jakub Rup
0

Puisque j'interprète mes instructions cron en utilisant php et js, je ne peux pas utiliser bash. Enfin , je trouve qu'il est en effet possible avec Cron juste:

0 30 8 * 1/1 MON#1

J'espère que ceci aide quelqu'un d'autre. Quoi qu'il en soit, je vous souhaite à tous une belle journée. :-)

kramer65
la source
Ce n'est pas du cron, c'est peut-être du quartz
sivann
-1
0 9 1-7 * 1 * 

Cela fonctionnera tous les lundis de chaque mois.

SIBHI S
la source
Une réponse a été acceptée, votre réponse est-elle meilleure, différente ou utile sur une version plus récente, etc.
mic84