¿Cómo puedo escribir un bash script para reiniciar el proceso si se muere?

Tengo un script en python que va a ser la comprobación de una cola y realizar una acción en cada elemento:

# checkqueue.py
while True:
  check_queue()
  do_something()

¿Cómo puedo escribir un script en bash que se compruebe si se está ejecutando, y si no, empezar. Aproximadamente el siguiente pseudo-código (o tal vez debería hacer algo como ps | grep?):

# keepalivescript.sh
if processidfile exists:
  if processid is running:
     exit, all ok

run checkqueue.py
write processid to processidfile

Voy a llamar a que a partir de un crontab:

# crontab
*/5 * * * * /path/to/keepalivescript.sh
  • Sólo para agregar esto para el año 2017. Uso supervisord. crontab no es lo que piensa hacer este tipo de tarea. Un script de bash que es terrible en la emisión de el error real. stackoverflow.com/questions/9301494/…
  • Cómo sobre el uso de inittab y reaparecen en lugar de otro no-soluciones de sistema? Consulte superuser.com/a/507835/116705
InformationsquelleAutor Tom | 2009-03-30

7 Kommentare

  1. 605

    Evitar PID-archivos, trabajos, o cualquier otra cosa que se intenta evaluar los procesos que no son sus hijos.

    Hay una muy buena razón por la que en UNIX, SOLO puede esperar de sus hijos. Cualquier método (ps análisis, pgrep, el almacenamiento de un PID, …), que trata de evitar que es imperfecto y tiene agujeros en ella. Acaba de decir no.

    Lugar usted necesita el proceso que supervisa el proceso de el proceso de’ padre de familia. ¿Qué significa esto? Esto significa que sólo el proceso que comienza su proceso de forma fiable puede esperar a que termine. En bash, esto es absolutamente trivial.

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

    El anterior fragmento de código bash ejecuta myserver en un until bucle. La primera línea comienza myserver y espera a que termine. Cuando se termina, until comprueba su estado de salida. Si el estado de salida es 0, significa que se terminó correctamente (lo que significa que usted pidió que se apague, de alguna manera, y lo hizo con éxito). En ese caso no queremos reiniciar (sólo pedimos que se apague!). Si el estado de salida es no 0, until va a ejecutar el cuerpo del bucle, el cual emite un mensaje de error en STDERR y se reinicia el bucle (volver a la línea 1) después de 1 segundo.

    ¿Por qué tenemos que esperar un segundo? Porque si algo está mal con la secuencia de inicio de myserver y se bloquea de inmediato, usted tendrá una muy intensivos en un bucle constante de reiniciar y estrellarse en sus manos. El sleep 1 quita la tensión de eso.

    Ahora todo lo que necesita hacer es iniciar este script en bash (de forma asincrónica, probablemente), y el monitoreo myserver y reinicie si es necesario. Si desea iniciar el monitor de arranque (hacer que el servidor «sobrevivir» se reinicia), usted puede programar en el manual de cron(1) con un @reboot regla. Abre tu cron reglas con crontab:

    crontab -e

    A continuación, añadir una regla para iniciar el monitor de secuencia de comandos:

    @reboot /usr/local/bin/myservermonitor

    Alternativamente, mire inittab(5) y /etc/inittab. Usted puede agregar una línea en la que han myserver inicio a una cierta init nivel y haberse regenerado de forma automática.


    Editar.

    Permítanme añadir algo de información sobre por qué no utilizar PID archivos. Mientras que son muy populares; también son muy imperfectos y no hay ninguna razón por qué no simplemente se hacen de la manera correcta.

    Considere esto:

    1. PID reciclaje (matando el proceso incorrecto):

      • /etc/init.d/foo start: inicio foo, escribir foo‘s PID para /var/run/foo.pid
      • Un rato más tarde: foo muere de alguna manera.
      • Un rato más tarde: cualquier proceso aleatorio que se inicia (llamada bar) toma una al azar PID, se imagina tomando foo‘s antiguo PID.
      • Observa foo‘s gone: /etc/init.d/foo/restart lee /var/run/foo.pid, comprueba para ver si sigue vivo, encuentra bar, piensa que es foo, lo mata, se inicia una nueva foo.
    2. PID archivos obsoletos. Usted necesita más complicado (o debería decir, no es trivial) de la lógica para comprobar si el archivo PID está obsoleto, y que toda la lógica se vuelva vulnerable a 1..

    3. ¿Qué pasa si usted no tiene acceso de escritura o que están en un entorno de solo lectura?

    4. Es inútil overcomplication; ver cómo simple, mi ejemplo anterior. No hay necesidad de complicar que, en todo.

    Ver también: Son PID-archivos aún errónea al hacerlo ‘a la derecha’?

    Por el camino; incluso peor que el PID de archivos es el análisis de ps! No vuelvas a hacer esto.

    1. ps es muy transportables. Mientras se encuentran en casi todos los sistemas UNIX; sus argumentos varían mucho si quieres no la salida estándar. Y la salida estándar es SÓLO para el consumo humano, no para secuencias de comandos de análisis!
    2. Análisis ps conduce a una gran cantidad de falsos positivos. Tomar la ps aux | grep PID ejemplo, y ahora imagina alguien el inicio de un proceso con un número en algún lugar como argumento que resulta ser el mismo como el PID que miraba a su demonio! Imaginemos a dos personas a partir de una sesión de X y grepping X para matar a los suyos. Es todo tipo de malas.

    Si usted no desea manejar el proceso mismo; hay algunas muy buenas sistemas de ahí que actuará como monitor para sus procesos. Buscar en runit, por ejemplo.

    • Usted puede añadir algo de código para enviar un mensaje o detener el bucle si se reinicia muchas veces en un corto período de tiempo.
    • +1 la mayoría de la respuesta correcta. Pero son un poco demasiado pragmático acerca de pid archivos… SysV init scripts se basan en gran medida en el pid de archivos, sobre todo porque el inicio y la parada de los estados en sus diferentes pgids.
    • Oficina principal: no creo que sea necesario. Se acaba de complicar la aplicación por ninguna buena razón. La simplicidad es siempre más importante; y si se reinicia a menudo, el sueño evitará tener cualquier impacto negativo sobre los recursos de su sistema. Ya hay un mensaje de todos modos.
    • Sé PID archivos se utilizan en todas partes. Esto no significa que ellos no son tan imperfectos como lo eran antes. Inicio foo, puesto que su PID en foo.pid. Foo muere. Algo se inicia en algún lugar, se toma una al azar PID que pasa a ser uno de los foo había. Detener foo va a matar un proceso equivocado!
    • Sólo root tiene acceso a /etc/inittab – ¿cómo sería un mero usuario asegurarse de que el proceso siempre se reinicia en una manera que pueda manejar tanto el bloqueo de un proceso y un reinicio del sistema?
    • stackoverflow.com/questions/822797/about-the-pid-of-the-process/…
    • Suena claro y fácil hasta que usted no necesita para administrar algún proceso con el tiempo de espera sin que la aplicación de la lógica en el proceso hijo. No es conveniente y fácil de usar integrado en el método para hacerlo.
    • sé que esto es ingenuo… la Ejecución de un script como este y luego tener un 2do server ping de servidor 1 para ver si el servicio es el mejor de la paz de la mente que puedo conseguir, supongo. Hay realmente no ninguna 2ª capa para asegurarse de que el script se está ejecutando. Me refiero a ¿por qué no ser que el script no está haciendo nada.
    • trampa ‘~/.bin/pánico’ EXIT; # se trata simplemente de locos hablar o hacer más seguro?
    • cron ha @reboot especificación de tiempo
    • Cómo intensivo de los recursos es un bucle y va a hacer una diferencia en el uso de sueño mayor que 1?
    • No hay consumo de recursos cuando el programa se comporta. Si existe inmediatamente en el inicio, de forma continua, el consumo de recursos con un sueño 1 es absolutamente insignificante.
    • Pueden creer que yo soy solo ver a esta respuesta. Muchas gracias!
    • Por desgracia, mi proceso no muere y el retorno de error en caso de error. Todavía necesito para restablecer automáticamente.
    • usted puede hacer la anterior bucle sin probar el proceso de » salir del código while true; do myprocess; done pero tenga en cuenta que ahora no hay manera de detener el proceso.
    • El problema era que el proceso no siempre salir… me fijo que en el código, sin embargo, y ahora estoy usando tu respuesta.
    • Yo estaba escribiendo un monitor de procesos para mi autossh túneles, y se buscó la mejor práctica para comprobar el proceso de vida basado en el pid. Tuve que desechar la mayor parte del código ya había escrito, te odio 😉 Ahora es tan simple y eficiente, gracias a usted!
    • Si bash que se está ejecutando la secuencia de comandos proporcionada es cerrado, a continuación, el proceso que fue lanzado todavía está siendo ejecutado. Y eso es un problema para mí.
    • La única manera de obligar a los padres a matar al niño en la salida en bash es convertir al niño en un puesto de trabajo y de la señal es: trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; done
    • Quiero saber si esta solución combinada con un archivo PID es todavía deficiente stackoverflow.com/questions/25906020/…
    • Podría un puerto específico específicos para el proceso de ser lanzado por el bash proceso? Yo ussualy uso nohup ./start -Dhttp.port=9001. Puede ser especificado en el bash?
    • Esto no tiene nada que ver con bash. Lea la documentación sobre el comando que especifica los argumentos. También, por favor no utilice nohup.
    • He intentado la solución en este comando 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 pero justo se cierra con un mensaje de error «No such file or directory Server «myserver» se estrelló con el código de salida 127. Respawning..`. Alguna idea de por qué?
    • no en el tema aquí; además, su comando de mentiras, ya no hay ni siquiera una mención de «miservidor» en ella. Usted sólo tiene que utilizar la correcta comando rsync, esto no tiene nada que ver con esta cuestión. Asegúrese de que el comando funciona por sí mismo primero!
    • El comando funciona bien. Puedo transferir archivos desde host:/tmp /tmp – no necesito un «miservidor». ¿Por qué es OT a preguntar por qué una solución genérica no parece ser genérico?
    • Quitar las comillas dobles. Código nunca debe ser citado. until command, no until "command".
    • así que, ¿cómo puedo iniciar el script de bash de forma asincrónica? provocar que el servidor muere cuando me sale de mi terminal. Pantalla tal vez?
    • ¿Cómo sería una señal «miservidor» para detener correctamente? Sobre todo si puedo usar la pantalla de inicio y se desprenden de la secuencia de comandos bash?
    • ¿Cómo es que esta no es la solución aceptada?
    • Soy capaz de crear un envoronment variable en el script que es utilizado por el programa?
    • cualquier variable de entorno que se declara en la secuencia de comandos antes de ejecutar el programa será exportada al programa. Utilice, por ejemplo. export MYVAR=myvalue

  2. 28

    Echar un vistazo a monit (http://mmonit.com/monit/). Se encarga de iniciar, detener y reiniciar la secuencia de comandos y puede hacer los controles de salud más se reinicia si es necesario.

    O hacer un simple script:

    while true
    do
    /your/script
    sleep 1
    done
  3. 8

    La manera más sencilla de hacerlo es utilizando el rebaño en el archivo. En la secuencia de comandos de Python te gustaría hacer

    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 se puede probar, si se está ejecutando:

    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

    Pero, por supuesto, usted no tiene que probar, porque si ya está en ejecución y se reinicia, va a salir con 'other instance already running'

    Cuando el proceso muere, todo es descriptores de archivo se cierra y todos los bloqueos se eliminan automáticamente.

    • posiblemente se podría simplificar un poco por la eliminación de la secuencia de comandos bash. ¿qué sucede si la secuencia de comandos de python se bloquea? es el archivo desbloqueado?
    • Archivo de bloqueo se libera tan pronto como la aplicación se detiene, ya sea mediante su destrucción, de forma natural o estrellarse.
    • ser un poco más precisos — el bloqueo ya no está activa tan pronto como el identificador de archivo es sobre se cierra. Si la secuencia de comandos de Python nunca cierra el identificador de archivo por la intención, y se asegura de que no se cierra de forma automática a través del archivo de objeto de recolección de basura, luego de cerrarlo probablemente significa que la secuencia de comandos salido / fue asesinado. Esto funciona incluso con los reinicios y tal.
    • Hay formas mucho mejores de utilizar flock… de hecho, el hombre de la página de forma explícita se muestra cómo! exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd" es el bash equivalente a su Python, y deja el bloqueo (por lo que si usted, a continuación, exec un proceso, el bloqueo permanecerá recluido hasta que el proceso de las salidas).
    • Yo votada abajo porque su código es incorrecto. El uso de flock es la manera correcta, pero los scripts están equivocados. El único comando que usted necesita para establecer en el crontab es: flock -n /tmp/script.lock -c '/path/to/my/script.py'
  4. 6

    Debe utilizar monit, un estándar de unix herramienta que puede controlar las cosas diferentes en el sistema y reaccionar en consecuencia.

    De la documentación: http://mmonit.com/monit/documentation/monit.html#pid_testing

    proceso de verificación de checkqueue.py con pidfile /var/run/checkqueue.pid 
    si se cambia pid luego exec "checkqueue_restart.sh" 
    

    También puede configurar monit a un correo electrónico cuando se hace un reinicio.

    • Monit es una gran herramienta, pero es que no estándar en el sentido formal de ser especificado en POSIX o SUSV.
  5. 5
    if ! test -f $PIDFILE || ! psgrep `cat $PIDFILE`; then
        restart_process
        # Write PIDFILE
        echo $! >$PIDFILE
    fi
    • fresco, que de consistencia a algunos de mis pseudo código bastante bien. dos esto suceda: 1) ¿cómo puedo generar PIDFILE? 2) ¿cuál es psgrep? no en ubuntu server.
    • ps grep es una pequeña aplicación que hace lo mismo que ps ax|grep .... Usted puede simplemente instalar o escribir una función para que: la función de psgrep() {ps ax|grep -v grep|grep -q «$1»}
    • Acabo de notar que no había respondido a la primera pregunta.
    • En realidad servidor ocupado, es posible que la EPI son reciclados antes de comprobar.
  6. 2

    No estoy seguro de cómo portátil es a través de sistemas operativos, pero usted puede comprobar si su sistema contiene la ‘ejecución de un comando, es decir, «el hombre de ejecución de uno».
    Específicamente, este conjunto de comandos que incluye el ‘run-uno-constantemente», que parece ser exactamente lo que se necesita.

    Desde la página man:

    de ejecución de una constante COMANDO [ARGS]

    Nota: obviamente, esto podría ser llamado desde dentro de la secuencia de comandos, pero también se elimina la necesidad de tener un script en todo.

    • ¿Esto ofrece ninguna ventaja sobre la aceptación de la respuesta?
    • Sí, creo que es preferible utilizar un comando integrado que escribir una secuencia de comandos de shell que hace la misma cosa que se mantiene como parte del sistema base. Incluso si la funcionalidad es necesaria como parte de una secuencia de comandos de shell el comando anterior también podría ser utilizado por lo que es relevante para un shell scripting pregunta.
    • Esto no es «integrada»; si es instalado por defecto en algunas distribuciones, su respuesta probablemente debería especificar la distro y lo ideal sería que incluye un puntero para donde descargarlo si lo tuyo no es uno de ellos).
    • Parece que es un Ubuntu utilidad; pero es opcional, incluso en Ubuntu. manpages.ubuntu.com/manpages/bionic/man1/run-one.1.html
  7. 1

    He utilizado la siguiente secuencia de comandos con gran éxito en numerosos servidores:

    pid=`jps -v | grep $INSTALLATION | awk '{print $1}'`
    echo $INSTALLATION found at PID $pid 
    while [ -e /proc/$pid ]; do sleep 0.1; done

    notas:

    • Que se busca un proceso java, así que me
      puede utilizar jps, esto es mucho más
      coherente a través de las distribuciones de
      ps
    • $INSTALLATION contiene suficiente de la vía de acceso del proceso que es totalmente inequívoco
    • Uso dormir mientras espera que el proceso de morir, evitar acaparando los recursos: a)

    Esta secuencia de comandos se utiliza para cerrar una instancia de ejecución de tomcat, que quiero apagar (y esperar) en la línea de comandos, por lo que se lanza como un proceso secundario, simplemente no es una opción para mí.

    • grep | awk todavía es un antipattern – quieres awk "/$INSTALLATION/ { print \$1 }" a confundir a la inútil grep en el Awk script, el cual puede encontrar las líneas regulares de la expresión de sí mismo muy bien, muchas gracias.

Kommentieren Sie den Artikel

Bitte geben Sie Ihren Kommentar ein!
Bitte geben Sie hier Ihren Namen ein

Pruebas en línea