Cómo asegurarse de que una aplicación siga ejecutándose en Linux

83

Estoy tratando de asegurarme de que un script siga ejecutándose en un servidor de desarrollo. Recopila estadísticas y proporciona un servicio web, por lo que se supone que persiste, pero algunas veces al día desaparece por razones desconocidas. Cuando nos damos cuenta, lo lanzamos nuevamente, pero es un dolor en la parte trasera y algunos usuarios no tienen permiso (o el conocimiento) para ejecutarlo.

El programador que hay en mí quiere dedicar unas horas a llegar al fondo del problema, pero la persona ocupada que hay en mí cree que debe haber una manera fácil de detectar si una aplicación no se está ejecutando y volver a iniciarla.

Sé que podría cron-script ps a través de grep:

ps -A | grep appname

Pero de nuevo, esa es otra hora de mi vida desperdiciada en hacer algo que ya debe existir ... ¿No hay una aplicación prefabricada que pueda pasar a un ejecutable (opcionalmente con argumentos) y que mantendrá un proceso ejecutándose indefinidamente?

En caso de que haga alguna diferencia, es Ubuntu.

Oli
fuente
1
Depende de si se pierden las estadísticas cuando el script no se está ejecutando, pero creo que el programador que hay en usted tiene razón: debería averiguar más sobre por qué el script no continúa indefinidamente.
Jonathan Leffler
1
Es más una utilidad de servicio a pedido que algo que constantemente procesa números. Si falla antes de guardar los datos, no se pierde nada; simplemente completará el trabajo la próxima vez que se ejecute.
Oli
La pregunta fue respondida en el estándar o la mejor manera de mantener vivo el proceso iniciado por init.d . Las soluciones incluyen el uso de systemd y /etc/inittab.
koppor

Respuestas:

37

Aviso: Upstart está en modo de mantenimiento y fue abandonado por Ubuntu que usa systemd. Uno debe consultar el manual de systemd para obtener detalles sobre cómo escribir la definición de servicio.

Dado que está utilizando Ubuntu, es posible que le interese Upstart , que ha reemplazado al tradicional sysV init . Una característica clave es que puede reiniciar un servicio si muere inesperadamente. Fedora se ha convertido en un advenedizo y Debian está en fase experimental, por lo que puede valer la pena investigarlo.

Sin embargo, esto puede ser excesivo para esta situación, ya que un script cron tardará 2 minutos en implementarse.

#!/bin/bash
if [[ ! `pidof -s yourapp` ]]; then
    invoke-rc.d yourapp start
fi
JimB
fuente
Debo señalar que configurar advenedizo para administrar su servicio y mantenerlo en ejecución es bastante simple (escribe un pequeño archivo de configuración). Esta solución es mucho más limpia, más simple y mejor que cualquier otro monitoreo "simple" basado en scripts cron / shell.
Thor
@thor - (tenga en cuenta que esto es de 2008, cuando el advenedizo era nuevo y la documentación era más difícil de conseguir). Estoy de acuerdo, la secuencia de comandos cron "simple" fue solo para ilustrar que una secuencia de comandos tampoco necesita ser compleja para hacer el trabajo.
JimB
Veo. He votado a favor su respuesta de todos modos al publicar mi comentario
thor
85

He usado un script simple con cron para asegurarme de que el programa se esté ejecutando. Si no es así, lo iniciará. Puede que esta no sea la solución perfecta que está buscando, pero es simple y funciona bastante bien.

#!/bin/bash
#make-run.sh
#make sure a process is always running.

export DISPLAY=:0 #needed if you are running a simple gui app.

process=YourProcessName
makerun="/usr/bin/program"

if ps ax | grep -v grep | grep $process > /dev/null
then
    exit
else
    $makerun &
fi

exit

Luego, agregue un trabajo cron cada minuto o cada 5 minutos.

Chris Wendt
fuente
2
Eso es genial. Sobrevivirá a un reinicio y no tendrá que instalar nada.
Ian Purton
Lo he usado yo mismo porque no requiere privilegios de root para instalarlo.
JohnMudd
¿Qué sería process namesi quisiera mantener un script de Python en ejecución?
Usuario
@User Use ps ax | grep XXXpara enumerar solo su proceso, luego XXX será.
sauce fuerte
11
Como cron de una sola línea, ejecútelo una vez por minuto:* * * * * ps aux|grep -v grep|grep -q YourProcessName || /usr/bin/program &
ACK_stoverflow
43

Monit es perfecto para esto :)

Puede escribir archivos de configuración simples que le digan a monit que mire, por ejemplo, un puerto TCP, un archivo PID, etc.

monit ejecutará un comando que usted especifique cuando el proceso que está monitoreando no esté disponible / use demasiada memoria / esté fijando la CPU durante demasiado tiempo / etc. También mostrará una alerta por correo electrónico que le indicará lo que sucedió y si podría hacer algo al respecto.

Lo usamos para mantener una gran cantidad de nuestros sitios web en funcionamiento y, al mismo tiempo, nos avisa cuando algo va mal.

- Tu fiel empleado, Monit

Gareth
fuente
19
¿Cómo mantienes a Monit funcionando?
JohnMudd
2
Este es bastante difícil de aprender. Solo quiero reiniciar un script (en lugar de un servicio) y leí su documento durante horas, pero no pude resolverlo.
Tyler Long
21

Si está usando una distribución basada en systemd como Fedora y versiones recientes de Ubuntu, puede usar la capacidad "Reiniciar" de systemd para los servicios. Puede configurarse como un servicio del sistema o como un servicio de usuario si necesita ser administrado y ejecutado por un usuario en particular, que es más probable que sea el caso en la situación particular de OP.

La opción Reiniciar toma uno de no , on-success, on-failure, on-abnormal, on-watchdog, on-abort, o always.

Para ejecutarlo como usuario, simplemente coloque un archivo como el siguiente en ~/.config/systemd/user/something.service:

[Unit]
Description=Something

[Service]
ExecStart=/path/to/something
Restart=on-failure

[Install]
WantedBy=graphical.target

entonces:

systemctl --user daemon-reload
systemctl --user [status|start|stop|restart] something

No se necesitan privilegios de root / modificación de los archivos del sistema, no se necesitan trabajos cron, no hay nada que instalar, es muy flexible (consulte todas las opciones de servicio relacionadas en la documentación).

Consulte también https://wiki.archlinux.org/index.php/Systemd/User para obtener más información sobre el uso de la instancia systemd por usuario.

Raman
fuente
Gran respuesta, pero ~ / .config / systemd / user / something.service fue, para mí, un poco ambiguo. ¿Es la parte "usuario" literalmente "usuario" o como "su nombre de usuario"? Si es "su nombre de usuario", me parece redundante ya que está creando este archivo en su directorio personal. Editar: parece que es literalmente "usuario"
fivedogit
8

He utilizado de cron "killall -0 nombre de programa || /etc/init.d/programname start". kill generará un error si el proceso no existe. Si existe, enviará una señal nula al proceso (que el kernel ignorará y no se molestará en transmitir).

Este modismo es fácil de recordar (en mi humilde opinión). Generalmente utilizo esto mientras todavía estoy tratando de descubrir por qué el servicio en sí está fallando. En mi humilde opinión, un programa no debería desaparecer inesperadamente :)


fuente
7

Pon tu carrera en un bucle, para que cuando salga, se ejecute de nuevo ... while (true) {run my app ..}

Klathzazt
fuente
4
Si el script está muriendo por razones desconocidas, es probable que también cancele el script de bucle, ¿no?
Gareth
4
Estoy con Garath, si el sistema está matando procesos de larga ejecución, entonces el ciclo sugerido, que comenzaría antes de la aplicación, se eliminaría primero.
ekerner
2
Para responder a sus dos comentarios: No, si el script muere por razones desconocidas, entonces el script de bucle no se ve afectado porque se ejecuta en un proceso separado, pero sí, si el sistema está matando aleatoriamente procesos de larga ejecución, esto aún sería un problema - Sin embargo, dudo que ese sea el caso. El resto del sistema no se informó como afectado y está lleno de otros procesos de larga ejecución que también se habrían reiniciado (solo se mencionó que este script tiene un problema).
Klathzazt
4

No pude hacer que la solución de Chris Wendt funcionara por alguna razón, y fue difícil de depurar. Este es prácticamente el mismo pero más fácil de depurar, excluye bash de la coincidencia de patrones. Para depuración basta con ejecutar: bash ./root/makerun-mysql.sh. En el siguiente ejemplo con mysql-server, simplemente reemplace el valor de las variables para processy makerunpara su proceso.

  • Cree un script BASH como este ( nano /root/makerun-mysql.sh):
#!/bin/bash
process="mysql"
makerun="/etc/init.d/mysql restart"
if ps ax | grep -v grep | grep -v bash | grep --quiet $process
then
    printf "Process '%s' is running.\n" "$process"
    exit
else
    printf "Starting process '%s' with command '%s'.\n" "$process" "$makerun"
    $makerun
fi
exit
  • Asegúrese de que sea ejecutable agregando los permisos de archivo adecuados (es decir chmod 700 /root/makerun-mysql.sh)

  • Luego agregue esto a su crontab ( crontab -e):

# Keep processes running every 5 minutes
*/5 * * * * bash /root/makerun-mysql.sh
cjohansson
fuente
1
Preste atención, en comparación con la solución de Chris Wendt, el script no se inicia aquí como tarea en segundo plano.
Mason
2

La superviseherramienta de daemontoolssería mi preferencia, pero entonces todo lo que escribe Dan J Bernstein es mi preferencia :)

http://cr.yp.to/daemontools/supervise.html

Tienes que crear una estructura de directorio particular para el script de inicio de tu aplicación, pero es muy simple de usar.

Asfa y Qazi
fuente
1

en primer lugar, ¿cómo se inicia esta aplicación? ¿Se bifurca a un segundo plano? ¿Ha comenzado con nohup .. & etc? Si es el último, verifique por qué murió en nohup.out, si es el primero, compile el registro.

En cuanto a su pregunta principal: puede cron o ejecutar otro proceso en segundo plano (no es la mejor opción) y usar pidof en un bashscript, bastante fácil:

if [ `pidof -s app` -eq 0 ]; then
    nohup app &
fi
gx.
fuente
1

Podría convertirlo en un servicio lanzado desde inittab (aunque algunos Linux se han movido a algo más nuevo en /etc/event.d). Estos sistemas integrados garantizan que su servicio siga funcionando sin tener que escribir sus propios scripts o instalar algo nuevo.

Paul Tomblin
fuente
1

Es un trabajo para un DMD (demonio de monitoreo de demonios). hay algunos alrededor; pero por lo general solo escribo un script que verifica si el demonio se está ejecutando, y lo ejecuto si no, y lo pongo en cron para que se ejecute cada minuto.

Javier
fuente
1

Consulte ' nanny' al que se hace referencia en el Capítulo 9 (p197 o más o menos) del "Unix Hater's Handbook" (una de varias fuentes para el libro en PDF).

Jonathan Leffler
fuente
1

Una forma sencilla y agradable de hacer esto es la siguiente:

  1. Escriba su servidor para que muera si no puede escuchar en el puerto que espera
  2. Configure un cronjob para intentar iniciar su servidor cada minuto

Si no se está ejecutando, se iniciará, y si se está ejecutando, no. En cualquier caso, su servidor siempre estará activo.

Casey Rodarmor
fuente
0

Creo que una mejor solución es probar la función también. Por ejemplo, si tuviera que probar un apache, no es suficiente con probar si existen procesos "apache" en los sistemas.

Si desea probar si apache está bien, intente descargar una página web simple y pruebe si su código único está en la salida.

Si no es así, elimine el apache con -9 y luego reinicie. Y envíe un correo a la raíz (que es una dirección de correo reenviado a las raíces de la empresa / servidor / proyecto).

peterh - Restablecer a Monica
fuente
1
Esto es verdad. Muchas de las soluciones de monitoreo sugeridas en otras respuestas brindan monitoreo de protocolo.
Oli
0

Es aún más simple:

#!/bin/bash

export DISPLAY=:0

process=processname
makerun="/usr/bin/processname"

if ! pgrep $process > /dev/null
then
    $makerun &
fi

Sin embargo, debe recordar para asegurarse de que el nombre del proceso sea único.

Radosław Ganczarek
fuente
0

Uno puede instalar cronjob monitoreando minuciosamente así:

crontab -l> crontab; echo -e '* * * * * export DISPLAY = ": 0.0" && para la aplicación en "eiskaltdcpp-qt" "Transmission-gtk" "nicotine"; do ps aux | grep -v grep | grep "$ aplicación"; hecho || "$ aplicación" & '>> crontab; crontab crontab

La desventaja es que los nombres de la aplicación que ingresa deben encontrarse en la ps aux|grep "appname"salida y, al mismo tiempo, pueden iniciarse con ese nombre:"appname" &

16851556
fuente