Minimalement cron, assurant une seule instance

9

Existe-t-il un moyen d'exécuter un script toutes les minutes (ou 2, ou 5, etc.), mais uniquement s'il n'est pas déjà en cours d'exécution?

Nous avons un ensemble de scripts qui doivent s'exécuter toutes les minutes. Parfois, ils peuvent commencer et terminer en une seconde, d'autres fois, ils peuvent durer 5 minutes.

Notre façon actuelle d'éviter les exécutions simultanées consiste à définir un is_runningindicateur dans chaque script et à quitter s'il est toujours activé. Mais cela n'est pas fiable (c'est-à-dire que des erreurs fatales entraîneraient l'activation du drapeau même après l'arrêt du script).

Nous pourrions écrire notre propre petit gestionnaire, mais je me demande s'il existe déjà une solution plus à la mode.

chroder
la source
+1 Cela m'intéresse également. Je ne connais pas la réponse, mais je suis intéressé par les solutions possibles.
Saif Bechan
Un cron minutieux sent beaucoup de "fais de moi un démon"
AD7six

Réponses:

8

une meilleure façon est d'utiliser à la flockplace d'un fichier pid. consultez la page de manuel: flock (1) . L'avantage est que, quelle que soit la façon dont un processus se termine / s'éteint, le verrou disparaît.

Javier
la source
3

J'aurais tendance à être d'accord avec la réponse du fichier pid de Warner. Cependant, la fonctionnalité suivante d'Anacron accomplit-elle cela?

-s
    Serialize execution of jobs. Anacron will not start a new job before the previous one finished. 

Je ne l'ai pas testé moi-même, je ne trouve pas la documentation d'anacron assez complète ...

Si vous voulez être particulièrement paresseux ;-) Vous pouvez simplement quitter le script si greping via la sortie ps renvoie le processus en cours d'exécution. Mais un fichier lock / pid est préférable.

Kyle Brandt
la source
anacron est une version plus récente de cron, il a donc plus de fonctionnalités que l'ancien standard. sur le «comment», il enregistre probablement un gestionnaire SIGCHLD, qui est déclenché lorsqu'un processus enfant meurt. ainsi il peut garder une trace de l'exécution des enfants et simplement sauter ces travaux.
Javier
@ Javier: Je suis en désaccord avec "anacron est une version plus récente de cron, donc il a plus de fonctionnalités que l'ancien standard." Il y a un certain chevauchement entre quoi anacronet cronfaire, mais ils résolvent différents problèmes. À l'aide de cron, comment commenceriez-vous un travail qui a été manqué parce qu'une machine était en panne? En utilisant anacron, comment voulez-vous commencer un travail tous les 25 décembre ou toutes les 5 minutes? (Vous pouvez, bien sûr, des solutions de contournement de script, mais ce n'est pas ce dont je parle.)
Pause jusqu'à nouvel ordre.
@Kyle: Cette option entraîne l'exécution simultanée de plusieurs travaux planifiés en même temps. Cela pourrait fonctionner pour le besoin du PO, mais cela bloquerait d'autres travaux ou d'autres travaux le bloqueraient. En outre, anacronne fonctionne pas à des périodes plus courtes qu'une journée.
pause jusqu'à nouvel ordre.
@Dennis Williamson: je suppose que vous avez raison, je n'ai pas vérifié les détails de l'historique. Mais je suppose que vous conviendrez que le projet anacron a commencé après que cron a été à peu près établi et qu'il est inspiré par celui-ci; il n'est donc pas surprenant qu'il possède des fonctionnalités que cron n'a pas. De plus, la question d'origine portait sur cron
Javier
1

C'est la bonne solution pour cette approche. En règle générale, un fichier pid est utilisé et un test pid est effectué par rapport au processus pour s'assurer qu'il fonctionne. S'il est périmé, le fichier de verrouillage sera supprimé et le processus s'exécutera de toute façon.

Toute intelligence supplémentaire serait généralement écrite dans le logiciel lui-même, en tant que démon, par opposition à l'exécution dans cron.

Warner
la source
1

Si vos scripts sont codés dans un langage qui prend en charge l'appel système flock (2), vous pouvez également flocker un fichier de verrouillage avec un appel de fonction. Exemple:

Si vous êtes bloqué avec Bash ou un autre langage de script qui ne le supporte pas, la solution déjà proposée avec flock (1) est également très bien.

PS Dans tous les cas, vous ne devez créer un fichier de verrouillage distinct qu'une seule fois (s'il n'existe pas déjà) et ne jamais le supprimer. Le répertoire "/ var / lock" est un bon endroit pour de tels fichiers.

famzah
la source
0

Ceci est une solution si votre script s'exécute en python (ou vous pouvez créer une commande python à exécuter avant la commande suivante) - J'ai rencontré ce problème exactement la semaine dernière, et bien que j'aie trouvé de bonnes solutions, j'ai décidé de faire un très package python simple et propre et téléchargé sur PyPI. Vous pouvez certainement verrouiller __file__pour ne pas avoir à penser à lui donner un nom de ressource personnalisé à verrouiller.

Installer avec: pip install quicklock

Son utilisation est extrêmement simple:

[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> # Let's create a lock so that only one instance of a script will run
...
>>> singleton('hello world')
>>>
>>> # Let's try to do that again, this should fail
...
>>> singleton('hello world')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/nate/live/gallery/env/lib/python2.7/site-packages/quicklock/quicklock.py", line 47, in singleton
    raise RuntimeError('Resource <{}> is currently locked by <Process {}: "{}">'.format(resource, other_process.pid, other_process.name()))
RuntimeError: Resource <hello world> is currently locked by <Process 24801: "python">
>>>
>>> # But if we quit this process, we release the lock automatically
...
>>> ^D
[nate@Nates-MacBook-Pro-3 ~/live] python
Python 2.7.6 (default, Sep  9 2014, 15:04:36)
[GCC 4.2.1 Compatible Apple LLVM 6.0 (clang-600.0.39)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> from quicklock import singleton
>>> singleton('hello world')
>>>
>>> # No exception was thrown, we own 'hello world'!

Jetez un œil: https://pypi.python.org/pypi/quicklock

Nate Ferrero
la source