J'ai un script python qui vérifiera une file d'attente et effectuera une action sur chaque élément:
# checkqueue.py
while True:
check_queue()
do_something()
Comment puis-je écrire un script bash qui vérifiera s'il est en cours d'exécution et sinon, le démarrera. À peu près le pseudo-code suivant (ou peut-être qu'il devrait faire quelque chose comme ps | grep
?):
# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
J'appellerai ça depuis une crontab:
# crontab
*/5 * * * * /path/to/keepalivescript.sh
Réponses:
Évitez les fichiers PID, les crons ou tout autre élément qui tente d'évaluer des processus qui ne sont pas leurs enfants.
Il y a une très bonne raison pour laquelle sous UNIX, vous ne pouvez attendre que vos enfants. Toute méthode (analyse ps, pgrep, stockage d'un PID, ...) qui essaie de contourner ce problème est défectueuse et comporte des trous béants. Dites simplement non .
Au lieu de cela, vous avez besoin du processus qui surveille votre processus pour être le parent du processus. Qu'est-ce que ça veut dire? Cela signifie que seul le processus qui démarre votre processus peut attendre de manière fiable qu'il se termine. En bash, c'est absolument trivial.
Le morceau de code bash ci-dessus s'exécute
myserver
enuntil
boucle. La première ligne démarremyserver
et attend qu'elle se termine. Une fois terminé,until
vérifie son état de sortie. Si l'état de sortie est0
, cela signifie qu'il s'est terminé avec élégance (ce qui signifie que vous lui avez demandé de s'arrêter d'une manière ou d'une autre, et il l'a fait avec succès). Dans ce cas, nous ne voulons pas le redémarrer (nous venons de lui demander de s'arrêter!). Si l'état de sortie n'est pas0
,until
exécutera le corps de la boucle, qui émet un message d'erreur sur STDERR et redémarre la boucle (retour à la ligne 1) après 1 seconde .Pourquoi attendons-nous une seconde? Parce que si quelque chose ne va pas avec la séquence de démarrage de
myserver
et qu'elle se bloque immédiatement, vous aurez une boucle très intensive de redémarrage et de plantage constant entre vos mains. Lesleep 1
enlève la souche à partir de cela.Maintenant, tout ce que vous devez faire est de démarrer ce script bash (de manière asynchrone, probablement), et il le surveillera
myserver
et le redémarrera si nécessaire. Si vous souhaitez démarrer le moniteur au démarrage (pour que le serveur "survienne" aux redémarrages), vous pouvez le planifier dans le cron (1) de votre utilisateur avec une@reboot
règle. Ouvrez vos règles cron aveccrontab
:Ajoutez ensuite une règle pour démarrer votre script de moniteur:
Alternativement; regardez inittab (5) et / etc / inittab. Vous pouvez y ajouter une ligne pour
myserver
commencer à un certain niveau d'initialisation et être réapparu automatiquement.Éditer.
Permettez-moi d'ajouter quelques informations sur pourquoi ne pas utiliser les fichiers PID. Bien qu'ils soient très populaires; ils sont également très imparfaits et il n'y a aucune raison pour que vous ne le fassiez pas simplement de la bonne façon.
Considère ceci:
Recyclage PID (tuant le mauvais processus):
/etc/init.d/foo start
: démarrerfoo
, écrirefoo
le PID de/var/run/foo.pid
foo
meurt en quelque sorte.bar
) prend un PID aléatoire, imaginez qu'il prennefoo
l'ancien PID.foo
parti:/etc/init.d/foo/restart
lit/var/run/foo.pid
, vérifie pour voir s'il est toujours vivant, trouvebar
, pense que c'estfoo
, tue, commence un nouveaufoo
.Les fichiers PID deviennent périmés. Vous avez besoin d'une logique trop compliquée (ou devrais-je dire, non triviale) pour vérifier si le fichier PID est périmé, et une telle logique est à nouveau vulnérable
1.
.Et si vous n'avez même pas accès en écriture ou si vous êtes dans un environnement en lecture seule?
C'est une surcompensation inutile; voyez à quel point mon exemple ci-dessus est simple. Pas besoin de compliquer ça du tout.
Voir aussi: Les fichiers PID sont-ils toujours défectueux lorsqu'ils le font «correctement»?
Au fait; pire encore que l'analyse des fichiers PID
ps
! Ne fais jamais ça.ps
est très impraticable. Bien que vous le trouviez sur presque tous les systèmes UNIX; ses arguments varient considérablement si vous souhaitez une sortie non standard. Et la sortie standard est UNIQUEMENT pour la consommation humaine, pas pour l'analyse par script!ps
conduit à BEAUCOUP de faux positifs. Prenons l'ps aux | grep PID
exemple, et imaginez maintenant que quelqu'un démarre un processus avec un nombre quelque part comme argument qui se trouve être le même que le PID avec lequel vous avez regardé votre démon! Imaginez deux personnes qui démarrent une session X et vous attendez que X tue la vôtre. C'est juste toutes sortes de mauvais.Si vous ne voulez pas gérer le processus vous-même; il existe des systèmes parfaitement bons qui serviront de moniteur pour vos processus. Regardez runit , par exemple.
la source
while true; do myprocess; done
mais notez qu'il n'y a maintenant aucun moyen d'arrêter le processus.trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; done
Jetez un œil à monit ( http://mmonit.com/monit/ ). Il gère le démarrage, l'arrêt et le redémarrage de votre script et peut effectuer des vérifications de l'état et redémarrer si nécessaire.
Ou faites un simple script:
la source
La façon la plus simple de le faire est d'utiliser flock on file. En script Python, vous feriez
Dans le shell, vous pouvez réellement tester s'il fonctionne:
Mais bien sûr, vous n'avez pas à tester, car s'il est déjà en cours d'exécution et que vous le redémarrez, il se fermera avec
'other instance already running'
À la fin du processus, tous ses descripteurs de fichiers sont fermés et tous les verrous sont automatiquement supprimés.
la source
flock
... en fait, la page de manuel montre explicitement comment!exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd"
est l'équivalent bash de votre Python, et laisse le verrou maintenu (donc si vous exécutez ensuite un processus, le verrou restera maintenu jusqu'à la fin de ce processus).flock
est la bonne façon, mais vos scripts sont incorrects. La seule commande que vous devez définir dans crontab est:flock -n /tmp/script.lock -c '/path/to/my/script.py'
Vous devez utiliser monit, un outil Unix standard qui peut surveiller différentes choses sur le système et réagir en conséquence.
Depuis les documents: http://mmonit.com/monit/documentation/monit.html#pid_testing
Vous pouvez également configurer monit pour vous envoyer un e-mail lors d'un redémarrage.
la source
la source
ps ax|grep ...
. Vous pouvez simplement l'installer ou écrire une fonction pour cela: function psgrep () {ps ax | grep -v grep | grep -q "$ 1"}Je ne sais pas à quel point il est portable sur les systèmes d'exploitation, mais vous pouvez vérifier si votre système contient la commande «run-one», c'est-à-dire «man run-one». Plus précisément, cet ensemble de commandes comprend «run-one-constant», ce qui semble être exactement ce dont vous avez besoin.
Depuis la page de manuel:
Remarque: évidemment, cela pourrait être appelé à partir de votre script, mais cela supprime également la nécessité d'avoir un script.
la source
J'ai utilisé le script suivant avec beaucoup de succès sur de nombreux serveurs:
Remarques:
$INSTALLATION
contient suffisamment de chemin de processus qui est c'est totalement sans ambiguïtéCe script est en fait utilisé pour arrêter une instance de tomcat en cours d'exécution, que je veux arrêter (et attendre) sur la ligne de commande, donc le lancer en tant que processus enfant n'est tout simplement pas une option pour moi.
la source
grep | awk
est toujours un contre- modèle - vous voulezawk "/$INSTALLATION/ { print \$1 }"
confondre l'inutilegrep
dans le script Awk, qui peut très bien trouver des lignes par expression régulière, merci beaucoup.J'utilise ceci pour mon processus npm
la source