129 votes

Empêcher l'exécution de tâches cron en double

J'ai programmé une tâche cron pour qu'elle s'exécute toutes les minutes, mais parfois le script prend plus d'une minute pour se terminer et je ne veux pas que les tâches commencent à "s'empiler" les unes sur les autres. Je suppose que c'est un problème de concurrence - c'est-à-dire que l'exécution de script doit être mutuellement exclusive.

Pour résoudre le problème, j'ai fait en sorte que le script recherche l'existence d'un fichier particulier (" fichier de verrouillage.txt ") et quitter s'il existe ou touch si ce n'est pas le cas. Mais ce n'est pas un bon sémaphore ! Existe-t-il une meilleure pratique que je devrais connaître ? Aurais-je dû écrire un démon à la place ?

2voto

Vous pouvez utiliser un fichier de verrouillage. Créez ce fichier lorsque le script démarre et supprimez-le lorsqu'il se termine. Le script, avant d'exécuter sa routine principale, devrait vérifier si le fichier de verrouillage existe et procéder en conséquence.

Les Lockfiles sont utilisés par les initscripts et par de nombreuses autres applications et utilitaires dans les systèmes Unix.

1 votes

C'est le uniquement de la façon dont je l'ai jamais vu mis en œuvre, personnellement. Je l'utilise selon la suggestion du mainteneur comme miroir pour un projet OSS.

2voto

Yuri Astrakhan Points 151

Je recommande d'utiliser run-one beaucoup plus simple que de s'occuper des verrous. Dans la documentation :

run-one est un script enveloppant 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 cronjobs, lorsque vous ne voulez pas plus d'une copie en cours d'exécution à la fois.

run-this-one est exactement comme run-one, sauf qu'il utilisera pgrep et kill pour trouver et tuer tout processus en cours d'exécution appartenant à l'utilisateur et correspondant aux commandes et arguments de la cible. Notez que run-this-one bloquera tout en essayant de tuer les processus correspondants, jusqu'à ce que tous les processus correspondants soient morts. processus correspondants soient morts.

run-one-constantly fonctionne exactement comme le run-one, sauf qu'il respawns "COMMAND [ARGS]" chaque fois que COMMAND sort (zéro ou non zéro).

continuer à fonctionner est un alias pour run-one-constantly.

run-one-until-success fonctionne exactement comme le run-one-constant sauf que qu'il relance "COMMAND [ARGS]" jusqu'à ce que COMMAND se termine avec succès (c'est-à-dire que se termine par zéro).

run-one-until-failure fonctionne exactement comme le run-one-constant sauf que qu'elle relance "COMMAND [ARGS]" jusqu'à ce que COMMAND se termine par un échec (c'est-à-dire que sorte non nulle).

1voto

Cela peut aussi être un signe que vous faites le mauvais choix. Si vos tâches sont exécutées de façon aussi rapprochée et aussi fréquente, vous devriez peut-être envisager de le décrôner et d'en faire un programme de type démon.

6 votes

Je ne suis pas du tout d'accord avec cela. Si vous avez quelque chose qui doit être exécuté périodiquement, en faire un démon est une solution de type "coup de massue pour une noix". Utiliser un fichier de verrouillage pour éviter les accidents est une solution parfaitement raisonnable que je n'ai jamais eu de problème à utiliser.

0 votes

@womble Je suis d'accord ; mais j'aime casser des noix avec des marteaux de forgeron ! :-)

1voto

dubiousjim Points 232

Votre démon cron ne devrait pas invoquer des tâches si des instances précédentes de celles-ci sont toujours en cours d'exécution. Je suis le développeur d'un démon cron. dcron et nous essayons spécifiquement d'empêcher cela. Je ne sais pas comment Vixie cron ou d'autres démons gèrent cela.

0 votes

Quelqu'un sait comment les autres crons gèrent cette situation ?

0voto

Sachin Patil Points 1

J'ai créé un jar pour résoudre un tel problème comme les crons dupliqués sont en cours d'exécution pourrait être java ou Shell cron. Il suffit de passer le nom du cron dans Duplicates.CloseSessions("Demo.jar"), ce qui va rechercher et tuer les pid existants pour ce cron, sauf le courant. J'ai implémenté une méthode pour faire ce genre de choses. String proname=ManagementFactory.getRuntimeMXBean().getName() ; String pid=proname.split("@")[0] ; System.out.println("PID actuel : "+pid) ;

            Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "});

            BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream()));
            String s = null;
            String killid="";

            while ((s = stdInput.readLine()) != null ) {                                        
                if(s.equals(pid)==false)
                {
                    killid=killid+s+" ";    
                }
            }

Et ensuite tuer la chaîne killid avec à nouveau la commande Shell.

0 votes

Je ne pense pas que cela réponde vraiment à la question.

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