Comment puis-je écrire un script bash pour redémarrer un processus s'il meurt?
J'ai un script python qui vais vérifier une file d'attente et l'exécution d'une action sur chaque élément:
# checkqueue.py
while True:
check_queue()
do_something()
Comment puis-je écrire un script bash qui va vérifier si il fonctionne, et si non, commencez. À 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
Je vais l'appeler à partir d'un crontab:
# crontab
*/5 * * * * /path/to/keepalivescript.sh
- Juste pour ajouter cet pour 2017. Utilisation supervisord. crontab n'est pas d'effectuer ce genre de tâche. Un script bash est terrible sur émettant de l'erreur réelle. stackoverflow.com/questions/9301494/...
- Comment sur l'utilisation de inittab et respawn à la place des autres solutions de système? Voir superuser.com/a/507835/116705
Vous devez vous connecter pour publier un commentaire.
Éviter PID-files, crons, ou quoi que ce soit d'autre qui tente d'évaluer les processus qui ne sont pas leurs enfants.
Il ya une très bonne raison pour laquelle, dans UNIX, vous ne pouvez attendre de vos enfants. Toute méthode (ps de l'analyse, pgrep, le stockage d'un PID, ...) qui essaie de contourner qui est défectueux et a des trous béants dans il. Juste dire pas.
Vous devez plutôt le processus qui surveille votre processus d'être le processus' parent. Qu'est-ce que cela signifie? Cela signifie que le processus qui commence votre processus fiable d'attente pour elle à la fin. En bash, c'est absolument insignifiant.
La pièce ci-dessus de bash s'exécute le code de
myserver
dans ununtil
boucle. La première ligne commencemyserver
et l'attend à la fin. Quand elle se termine,until
vérifie son état de sortie. Si le statut de sortie est0
, cela signifie, il a fini normalement (ce qui signifie que vous avez demandé la fermeture d'une certaine manière, et il l'a fait avec tant de succès). Dans ce cas, nous ne voulons pas le redémarrer (nous avons demandé la fermeture!). Si le statut de sortie est pas0
,until
va exécuter le corps de la boucle, qui émet un message d'erreur sur STDERR et de redémarrage de la boucle (retour à la ligne 1) après 1 seconde.Pourquoi nous faire attendre une seconde? Parce que si quelque chose ne va pas avec la séquence de démarrage de
myserver
et il se bloque immédiatement, vous aurez un très intensive de la boucle de la constante de redémarrer et de s'écraser sur vos mains. Lesleep 1
enlève la souche à partir que les.Maintenant tout ce que vous devez faire est de commencer ce script bash (de manière asynchrone, sans doute), et il surveillera
myserver
et de le redémarrer si nécessaire. Si vous souhaitez démarrer le moniteur de démarrage (la prise de serveur "survivre" redémarre), vous pouvez programmer dans votre cron de l'utilisateur(1) avec un@reboot
règle. Ouvrez votre cron règlescrontab
:Puis ajouter une règle pour commencer votre script de surveillance de:
Alternativement; regardez inittab(5) et /etc/inittab. Vous pouvez ajouter une ligne dans y ont
myserver
commencer à un certain niveau d'init et de repop automatiquement.Modifier.
Permettez-moi d'ajouter quelques informations sur les raisons de pas pour utiliser les fichiers PID. Alors qu'ils sont très populaires, ils sont également très imparfaite et il n'ya aucune raison pourquoi vous ne serait pas juste de faire de la bonne façon.
Considérez ceci:
PID de recyclage (en tuant le processus incorrect):
/etc/init.d/foo start
: démarrerfoo
, écrirefoo
s'PID pour/var/run/foo.pid
foo
meurt en quelque sorte.bar
) prend un hasard PID, imaginez-ilfoo
s'ancien PID.foo
's gone:/etc/init.d/foo/restart
lit/var/run/foo.pid
, vérifie si il est encore en vie, trouvebar
, pense que c'estfoo
, il tue, commence une nouvellefoo
.Les fichiers PID rassir. Vous avez besoin plus compliqué (ou devrais-je dire, non-trivial) logique pour vérifier si le fichier PID est vicié, et une telle logique est de nouveau vulnérable à
1.
.Que faire si vous n'avez même pas accès en écriture ou en lecture seule de l'environnement?
Il est inutile overcomplication; voir comment de simples mon exemple ci-dessus est. Pas besoin de compliquer que, à tous.
Voir aussi: Sont PID-fichiers encore imparfait en la faisant "droit"?
Par le chemin; encore pire que les fichiers PID est l'analyse
ps
! Ne jamais faire cela.ps
est très portables. Alors que vous trouver sur presque tous les systèmes UNIX; ses arguments varient grandement si vous voulez non-standard de sortie. Et la sortie standard est SEULEMENT pour la consommation humaine, pas de script d'analyse!ps
conduit à BEAUCOUP de faux positifs. Prendre laps aux | grep PID
exemple, et maintenant, imaginez quelqu'un au début d'un processus avec un nombre quelque part que l'argument qui se trouve être le même que le PID que vous avez regardé votre démon avec! Imaginez deux personnes de démarrer une session X et vous grepping de X pour tuer les vôtres. C'est juste toutes sortes de mauvais.Si vous ne voulez pas gérer le processus vous-même; il y a quelques parfaitement les systèmes de bons là-bas qui vont agir comme un moniteur pour votre processus. Regarder dans runit, par exemple.
/etc/inittab
- comment un simple utilisateur de s'assurer que certains processus obtient toujours redémarré dans une manière qui permettrait de gérer à la fois un processus de collision et un redémarrage du système?@reboot
spécification de tempswhile true; do myprocess; done
mais note qu'il y a aucun moyen d'arrêter le processus.trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; done
nohup ./start -Dhttp.port=9001
. Peut-il être spécifié dans le bash?until "rsync --exclude-from /rsync-exclude-list.txt -av --delete --progress --stats --human-readable --checksum --timeout=3600 --partial-dir /tmp/ rsync://host:/tmp/ /tmp"; do
mais il se ferme avec un message d'erreur "No such file or directory Server "monserveur" s'est écrasé avec le code de sortie 127. Les réapparitions..`. Des idées pourquoi?until command
, pasuntil "command"
.export MYVAR=myvalue
Ont un coup d'oeil à monit (http://mmonit.com/monit/). Il gère le démarrage, l'arrêt et le redémarrage de votre script, et peut faire des contrôles de santé plus redémarre si nécessaire.
Ou faire un simple script:
La façon la plus simple de le faire est d'utiliser troupeau sur fichier. Dans le script Python que vous feriez
Dans le shell vous permettent de tester si elle est en cours d'exécution:
Mais bien sûr, vous n'avez pas à tester, parce que si c'est déjà en cours d'exécution et que vous le redémarrez, il va sortir avec
'other instance already running'
Lorsque le processus meurt, tous les descripteurs de fichiers sont fermées et tous les verrous sont automatiquement supprimés.
flock
... en fait, la page de man démontre explicitement comment!exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd"
est le bash équivalent à votre Python, et laisse le verrou (ainsi, si vous exec d'un processus, la serrure restera détenu jusqu'à ce que le processus s'arrête).flock
est la façon correcte, mais vos scripts sont mauvais. La seule commande que vous avez besoin de mettre en crontab est:flock -n /tmp/script.lock -c '/path/to/my/script.py'
Vous devez utiliser monit, un standard d'unix outil qui peut surveiller des choses différentes sur le système et de réagir en conséquence.
De la documentation: http://mmonit.com/monit/documentation/monit.html#pid_testing
Vous pouvez également configurer monit pour vous envoyer des courriels quand il fait un redémarrage.
ps ax|grep ...
. Vous pouvez simplement l'installer ou écrire une fonction pour ça: fonction psgrep() {ps ax|grep -v grep|grep -q "$1"}Je ne suis pas sûr de savoir comment portable c'est à travers les systèmes d'exploitation, mais vous pouvez vérifier si votre système contient les " exécuter une commande, c'est à dire "l'homme de l'exécution de l'un".
Plus précisément, cet ensemble de commandes comprend l'exécution d'une permanence", qui semble être exactement ce qui est nécessaire.
De l'homme page:
Remarque: évidemment, cela pourrait être appelée à partir de votre script, mais ce qui élimine la nécessité d'avoir un script à tous.
J'ai utilisé le script suivant avec succès sur de nombreux serveurs:
notes:
pouvez utiliser des pc, c'est beaucoup plus
cohérent à travers les distributions de
ps
$INSTALLATION
contient assez de processus de chemin c'est que c'est totalement sans ambiguïtéCe script est en fait utilisé pour arrêter une instance en cours d'exécution de tomcat, que je veux arrêter (et attendre) à la ligne de commande, afin de le lancer comme un processus enfant n'est tout simplement pas une option pour moi.
grep | awk
est encore un antipattern - vous voulezawk "/$INSTALLATION/ { print \$1 }"
de confondre l'inutilegrep
dans le script Awk, qui peut trouver des lignes par expression régulière elle-même très bien, merci beaucoup.