295 votes

Comment puis-je écrire un script bash pour redémarrer un processus s'il meurt?

J'ai un script python qui vérifie une file d'attente et effectue 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, lancez-le. À peu près le pseudo-code suivant (ou peut-être devrait-il 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 l'appellerai d'un crontab:

 # crontab
*/5 * * * * /path/to/keepalivescript.sh
 

Merci d'avance.

744voto

lhunath Points 27045

É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. Juste dire non.

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 démarre votre processus fiable d'attente pour elle à la fin. En bash, c'est absolument insignifiant.

until myserver; do
    echo "Server 'myserver' crashed with exit code $?.  Respawning.." >&2
    sleep 1
done

La pièce ci-dessus de bash code s'exécute myserver en until boucle. La première ligne commence myserver et l'attend à la fin. Quand elle se termine, until vérifie son état de sortie. Si le statut de sortie est - 0, cela signifie que c'est terminé 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 n'est pas 0, 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 l' 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. L' sleep 1 enlève de la souche.

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 (serveur de "survivre" redémarre), vous pouvez programmer dans votre cron de l'utilisateur(1) avec un @reboot règle. Ouvrez votre cron règles avec crontab:

crontab -e

Puis ajouter une règle pour commencer votre script de surveillance:

@reboot /usr/local/bin/myservermonitor

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.


Edit.

Permettez-moi d'ajouter quelques informations sur les raisons de ne pas 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.

Réfléchissez à ceci:

  1. PID recyclage (en tuant le processus incorrect):

    • /etc/init.d/foo start: début foo, écrire foos'PID /var/run/foo.pid
    • Un peu plus tard: foo meurt en quelque sorte.
    • Un peu plus tard: tout processus aléatoire qui commence (appelons - bar) prend un hasard PID, l'imaginer en prenant foos'ancien PID.
    • Vous remarquez foo's gone: /etc/init.d/foo/restart lectures /var/run/foo.pid, vérifie si il est encore en vie, conclut bar, pense que c'est foo,, il tue, commence un nouveau foo.
  2. 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 à l' 1..

  3. Que faire si vous n'avez même pas accès en écriture ou en lecture seule de l'environnement?

  4. Il est inutile overcomplication; voir comment de simples mon exemple ci-dessus est. Pas besoin de compliquer que, à tous.

Par la route, encore pire que les fichiers PID est l'analyse ps! Ne jamais faire cela.

  1. 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!
  2. Analyse ps conduit à BEAUCOUP de faux positifs. Prendre l' ps 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! 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. Regardez dans les runit, par exemple.

49voto

Bernd Points 2107

Jetez un coup d’œil à monit ( http://mmonit.com/monit/ ). Il commence, arrête et redémarre votre script et peut faire des vérifications de santé plus des redémarrages si nécessaire.

Ou faire un script simple

 while 1
do
/your/script
sleep 1
done
 

11voto

vartec Points 53382

La manière la plus simple de le faire est d'utiliser flock on file. En script Python, vous feriez

 lf = open('/tmp/script.lock','w')
if(fcntl.flock(lf, fcntl.LOCK_EX|fcntl.LOCK_NB) != 0): 
   sys.exit('other instance already running')
lf.write('%d\n'%os.getpid())
lf.flush()
 

en shell, vous pouvez réellement tester son exécution:

 if [ `flock -xn /tmp/script.lock -c 'echo 1'` ]; then 
   echo 'it's not running'
   restart.
else
   echo -n 'it's already running with PID '
   cat /tmp/script.lock
fi
 

mais bien sûr vous n’avez pas à tester, car s’il est déjà en marche et que vous le redémarrez, il se terminera avec 'other instance already running'

A la mort du processus, tous les descripteurs de fichiers sont fermés et tous les verrous sont automatiquement supprimés.

6voto

clofresh Points 588

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.

À partir de la documentation: http://mmonit.com/monit/documentation/monit.html#pid_testing

le processus de vérification checkqueue.py avec pidfile /var/run/checkqueue.pid
 en cas de changement de pid puis exec "checkqueue_restart.sh"

Vous pouvez également configurer monit pour vous envoyer des courriels quand il fait un redémarrage.

5voto

soulmerge Points 37314
if ! test -f $PIDFILE || ! psgrep `cat $PIDFILE`; then
    restart_process
    # Write PIDFILE
    echo $! >$PIDFILE
fi

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X