28 votes

Crond calendrier de décalage de cinq minutes

Est-il possible de décaler un script cron programmé pour s'exécuter toutes les 5 minutes ?

J'ai deux scripts, le script 1 collecte certaines données d'une base de données et les insère dans une autre, le script 2 extrait ces données ainsi que beaucoup d'autres données et crée des rapports à partir de celles-ci. Les deux scripts doivent s'exécuter toutes les 5 minutes. Je veux décaler le script 2 d'une minute pour qu'il puisse créer un rapport à partir des nouvelles données. Par exemple, je veux que le script un s'exécute à :00, :05, :10, :15 [...] et que le script 2 s'exécute à :01, :06, :11, :16 [...] toutes les heures. Les scripts ne dépendent pas les uns des autres, et le script 2 doit s'exécuter que le script un ait été réussi ou non. Mais il serait utile que les rapports aient les dernières données. Est-ce possible avec cron ?

Post ;
J'ai pensé à utiliser les deux commandes dans un script shell pour qu'elles s'exécutent immédiatement l'une après l'autre, mais cela ne fonctionnerait pas, parfois le script 1 peut rester bloqué en attente d'API externes, etc. donc il pourrait prendre jusqu'à 15 minutes pour s'exécuter, mais le script 2 doit s'exécuter toutes les 5 minutes, donc le faire de cette manière arrêterait/différerait l'exécution du script 2. Si je pouvais le configurer dans Cron, cela signifierait que le script 2 s'exécuterait peu importe ce que fait le script 1

56voto

Caleb Points 11393

Le champ d'entrée de minute pour crontab accepte un opérateur "par incréments" qui est un peu déroutant car il ressemble à un opérateur "divisé par" mathématique mais ne l'est pas. Vous verrez le plus souvent utilisé quelque chose comme ce qui suit. Notez que cela ne trouve pas les nombres divisibles par cinq mais prend plutôt chaque cinquième élément d'un ensemble :

 */5 * * * * commande

Cela indique à cron de faire correspondre chaque cinquième élément (/5) de l'ensemble des minutes 0-59 (*) mais vous pouvez changer l'ensemble comme ceci :

 1-59/5 * * * * commande

Cela prendrait chaque cinquième élément de l'ensemble 1-59, exécutant votre commande aux minutes 6, 11, 16, etc.

Si vous avez besoin de décalages plus fins que d'une minute, vous pouvez le faire en utilisant la commande sleep comme partie de votre crontab comme ceci :

 */5 * * * * sleep 15 && commande

Cela exécuterait votre tâche toutes les cinq minutes, mais la commande ne démarrerait pas réellement avant 15 secondes après la minute. Pour les tâches de courte durée où être quelques secondes après quelque chose d'autre fait toute la différence mais que vous ne voulez pas être en retard d'une minute complète, c'est une astuce assez simple.

4 votes

C'est une meilleure réponse que celle acceptée. Définir le décalage via la plage est beaucoup plus propre que le sommeil.

13voto

Eric Noob Points 531

Vous pouvez exécuter des scripts quand vous le souhaitez en utilisant cron. Si vous souhaitez exécuter le script 1 toutes les 5 minutes, vous pourriez commencer de cette manière :

*/5 * * * * /chemin/vers/script1

Mais c'est vraiment juste une façon abrégée pour :

0,5,10,15,20,25,30,35,40,45,50,55 * * * * /chemin/vers/script1

Si vous souhaitez exécuter le script 2 une minute après le script 1, vous pouvez faire ceci :

1,6,11,16,21,26,31,36,41,46,51,56 * * * * /chemin/vers/script2

Vous pourriez également faire ceci :

*/5 * * * * /chemin/vers/script1
*/5 * * * * /chemin/vers/script2

Et ensuite, au début du script 2, dormir pendant une minute :

sleep 60

8 votes

Placer le sleep dans le script lui-même est une astuce moche qui rend pénible l'exécution manuelle du script à partir de l'invite de commande. Il existe une méthode moins moche pour contourner cela en intégrant la pause dans l'entrée de crontab, mais une manière encore plus élégante est simplement de décaler les tâches en utilisant la notation correcte de crontab, sur laquelle votre réponse ne se penche pas.

13voto

Kurt Points 241

Vous pouvez indiquer un décalage horaire avec le symbole +. Par exemple, pour s'exécuter à :01, :06, :11, :16 [...], créez une tâche comme

*/5+1 * * * * commande

9 votes

Cela ne semble pas fonctionner dans certaines versions de cron

2 votes

Quelle version de cron utilisez-vous qui prend en charge cette syntaxe ? Cronie ne semble pas le supporter.

0 votes

J'ai Cronie sur CentOS7, donc je ne vais pas essayer cette solution en premier.

2voto

Tor Valamo Points 14209

Cela a fonctionné pour moi :

1/5 * ? * * *

Où 1 est le décalage en minutes. Donc si vous voulez un décalage de trois minutes :

3/5 * ? * * *

Cela fonctionne dans les paramètres de planification AWS

0 votes

Malheureusement, cela ne fonctionne pas avec Ubuntu 21.10 erreurs de mauvaise minute dans le fichier crontab, impossible d'installer.

1voto

Walf Points 253

Ceci est un problème XY. Décaler cron par rapport à des intervalles d'heure entière, ou des fractions communes de celles-ci, peut être généralement utile pour réduire les processus coïncidants, mais cette question déclare explicitement que le décalage vise à résoudre une dépendance. Bien que nous soyons informés que le script 2 doit s'exécuter indépendamment de l'achèvement du script 1, il ne devrait certainement pas essayer de s'exécuter alors que le script 1 est en train de mettre à jour l'ensemble de données partagé. Utiliser le temps seul pour imposer une séquence crée un retard inutile entre les deux au mieux, et une condition de course au pire.

Il est préférable de les mettre dans la même ligne de travail cron pour créer la dépendance chronologique :

*/5 * * * * /chemin/vers/script1; /chemin/vers/script2

Le point-virgule sépare les commandes mais garantit qu'elles s'exécuteront toutes indépendamment du statut de sortie précédent.

Dans les cas où la deuxième commande doit s'exécuter seulement si la première commande est réussie, modifiez-la comme suit :

*/5 * * * * /chemin/vers/script1 && /chemin/vers/script2

Je pense que c'est un cas du dernier, où le rapport ne changera pas s'il est généré à partir de données anciennes, ou sera complètement incorrect s'il est généré à partir de données incomplètes, alors pourquoi en créer un autre jusqu'à ce qu'une exécution réussie du premier script ait eu lieu ? Renvoyez plutôt une copie mise en cache du rapport précédent ou rien du tout. Si le premier script a la moindre chance de s'exécuter plus longtemps que l'intervalle cron, il devrait utiliser un verrouillage de base (par exemple avec flock) pour garantir qu'il n'y aura pas d'exécutions concurrentes faisant des demandes en concurrence aux mêmes endroits.

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X