J'ai planifié l'exécution d'un travail cron toutes les minutes, mais parfois, le script prend plus d'une minute et je ne veux pas que les travaux commencent à se superposer les uns aux autres. J'imagine qu'il s'agit d'un problème de concurrence, c'est-à-dire que l'exécution du script doit s'exclure mutuellement.
Pour résoudre le problème, j’ai demandé au script de rechercher l’existence d’un fichier particulier (" lockfile.txt ") et de le quitter s’il existait ou touch
non. Mais ceci est un sémaphore assez moche! Existe-t-il une meilleure pratique que je devrais connaître? Aurais-je dû écrire un démon à la place?
la source
flock -n file command
etflock -n file -c command
?-c
la commande spécifiée est exécutée via un shell (comme indiqué dans la page de manuel), tandis que la forme "nue" (non-c
) est simplementexec
la commande donnée . Insérer quelque chose dans le shell vous permet d'effectuer des opérations similaires à celles du shell (telles que l'exécution de plusieurs commandes séparées avec;
ou&&
), mais vous ouvre également la porte aux attaques de développement du shell si vous utilisez une entrée non fiable.frequent_cron_job
commande (hypothétique) qui essayait de montrer qu'elle s'exécutait toutes les minutes. Je l'ai enlevé car il n'a ajouté rien d'utile, et a causé de la confusion (le vôtre, si personne d'autre ne l'a été au fil des ans).Le meilleur moyen en shell est d'utiliser flock (1)
la source
99
et>
c'est ainsi99> /...
En fait,
flock -n
peut être utilisé à la place delckdo
*, vous utiliserez donc le code des développeurs du noyau.En vous basant sur l'exemple de womble , vous écririez quelque chose comme:
BTW, regardant le code, tous
flock
,lockrun
etlckdo
faire exactement la même chose, il est donc juste une question de ce qui est plus facilement disponible pour vous.la source
Vous pouvez utiliser un fichier de verrouillage. Créez ce fichier au démarrage du script et supprimez-le à la fin. Avant d'exécuter sa routine principale, le script doit vérifier si le fichier de verrouillage existe et procéder en conséquence.
Les fichiers de verrouillage sont utilisés par les scripts d'initialisation et par de nombreuses autres applications et utilitaires dans les systèmes Unix.
la source
Vous n'avez pas spécifié si vous voulez que le script attende ou non l'exécution précédente. Par "Je ne veux pas que les travaux commencent à" s'empiler "les uns sur les autres", je suppose que vous sous-entendez que vous voulez que le script se ferme s'il est déjà en cours d'exécution,
Donc, si vous ne voulez pas dépendre de lckdo ou similaire, vous pouvez le faire:
la source
Cela pourrait également être un signe que vous faites la mauvaise chose. Si vos tâches sont exécutées aussi étroitement et aussi fréquemment, vous devriez peut-être envisager de la décoder et d'en faire un programme de type démon.
la source
Votre démon cron ne devrait pas appeler des travaux si leurs instances précédentes sont toujours en cours d'exécution. Je suis le développeur d'un démon cron dcron , et nous essayons précisément d'empêcher cela. Je ne sais pas comment Vixie Cron ou d'autres démons gèrent cela.
la source
Je recommanderais d'utiliser la commande run-one - beaucoup plus simple que de traiter avec les verrous. De la docs:
run-one est un script wrapper qui n'exécute pas plus d'une instance unique d'une commande avec un ensemble unique d'arguments. Ceci est souvent utile avec les tâches cron, lorsque vous ne voulez pas exécuter plus d’une copie à la fois.
run-this-one est exactement comme run-one, sauf qu'il utilisera pgrep et kill pour rechercher et tuer tous les processus en cours d'exécution détenus par l'utilisateur et correspondant aux commandes et arguments cibles. Notez que run-this-one bloquera tout en essayant de tuer les processus correspondants jusqu'à ce que tous les processus correspondants soient morts.
run-one- fonctionne exactement de la même manière que run-one, sauf qu'il rappelle "COMMAND [ARGS]" à chaque sortie de COMMAND (zéro ou différent de zéro).
Keep-one-running est un alias pour run-one-constamment.
run-one-Until-Success fonctionne exactement comme run-one-constant sauf qu'il rappelle "COMMAND [ARGS]" jusqu'à ce que COMMAND se ferme correctement (c.-à-d. qu'il quitte zéro).
run-one-jusqu'à-échec fonctionne exactement comme run-one-constamment, sauf qu'il rappelle "COMMAND [ARGS]" jusqu'à ce que COMMAND se termine avec un échec (c'est-à-dire des sorties différentes de zéro).
la source
Maintenant que systemd est sorti, il existe un autre mécanisme de planification sur les systèmes Linux:
UNE
systemd.timer
Dans
/etc/systemd/system/myjob.service
ou~/.config/systemd/user/myjob.service
:Dans
/etc/systemd/system/myjob.timer
ou~/.config/systemd/user/myjob.timer
:Si l'unité de service est déjà activée lors de l'activation suivante du minuteur, une autre instance du service ne sera pas démarrée.
Une alternative, qui démarre le travail une fois au démarrage et une minute après la fin de chaque exécution:
la source
J'ai créé un bocal pour résoudre un problème tel que les doublons de crons exécutés pourraient être java ou cron shell. Il suffit de passer le nom du cron dans Duplicates.CloseSessions ("Demo.jar") pour rechercher et tuer le pid existant pour ce cron, sauf current. J'ai mis en place une méthode pour faire ce genre de choses. Proname de chaîne = ManagementFactory.getRuntimeMXBean (). GetName (); String pid = proname.split ("@") [0]; System.out.println ("PID actuel:" + pid);
Et puis tuez la chaîne killid avec à nouveau la commande shell
la source
@Philip Reynolds answer commencera à exécuter le code après le délai d’attente de 5 secondes sans obtenir le verrou. Après Flock ne semble pas fonctionner, j'ai modifié la réponse de @Philip Reynolds à
afin que le code ne soit jamais exécuté simultanément. Au lieu de cela, après 5 secondes d’attente, le processus se termine avec 1 s’il n’a pas encore obtenu le verrou.
la source