Tengo un script de Python que verificará una cola y realizará una acción en cada elemento:
# checkqueue.py
while True:
check_queue()
do_something()
¿Cómo escribo un script bash que verificará si se está ejecutando y, si no, inícielo? Aproximadamente el siguiente pseudocódigo (¿o tal vez debería hacer algo así ps | grep?):
# keepalivescript.sh
if processidfile exists:
if processid is running:
exit, all ok
run checkqueue.py
write processid to processidfile
Llamaré eso desde un crontab:
# crontab
*/5 * * * * /path/to/keepalivescript.sh

Respuestas:
Evite los archivos PID, crons o cualquier otra cosa que intente evaluar procesos que no sean sus hijos.
Hay una muy buena razón por la cual en UNIX, SOLO puede esperar a sus hijos. Cualquier método (análisis ps, pgrep, almacenamiento de un PID, ...) que intente solucionarlo es defectuoso y tiene agujeros enormes. Solo di que no .
En su lugar, necesita que el proceso que supervisa su proceso sea el padre del proceso. ¿Qué significa esto? Significa que solo el proceso que inicia su proceso puede esperar confiablemente a que termine. En bash, esto es absolutamente trivial.
La parte anterior del código bash se ejecuta
myserveren ununtilbucle. La primera línea comienzamyservery espera a que termine. Cuando termina,untilverifica su estado de salida. Si el estado de salida es0, significa que terminó con gracia (lo que significa que le pidió que se cerrara de alguna manera, y lo hizo con éxito). En ese caso, no queremos reiniciarlo (¡solo le pedimos que se apague!). Si el estado de salida no es0,untilejecutará el cuerpo del bucle, que emite un mensaje de error en STDERR y reinicia el bucle (de vuelta a la línea 1) después de 1 segundo .¿Por qué esperamos un segundo? Porque si algo está mal con la secuencia de inicio
myservery se bloquea de inmediato, tendrá un ciclo muy intenso de reinicio constante y bloqueo en sus manos. Elsleep 1quita la tensión de eso.Ahora todo lo que necesita hacer es iniciar este script bash (probablemente de forma asincrónica), y lo monitoreará
myservery reiniciará según sea necesario. Si desea iniciar el monitor en el arranque (haciendo que el servidor "sobreviva" los reinicios), puede programarlo en el cron de su usuario (1) con una@rebootregla. Abra sus reglas cron concrontab:Luego agregue una regla para iniciar su script de monitor:
Alternativamente; mira inittab (5) y / etc / inittab. Puede agregar una línea allí para
myservercomenzar en un cierto nivel de inicio y reaparecer automáticamente.Editar.
Permítanme agregar información sobre por qué no usar archivos PID. Si bien son muy populares; también son muy defectuosos y no hay razón para que no lo hagas de la manera correcta.
Considera esto:
Reciclaje de PID (matar el proceso incorrecto):
/etc/init.d/foo start: iniciofoo, escribafooel PID en/var/run/foo.pidfoomuere de alguna manera.bar) toma un PID aleatorio, imagínelo tomandofooel PID anterior.foode que se ha ido:/etc/init.d/foo/restartlee/var/run/foo.pid, verifica si todavía está vivo, lo encuentrabar, piensa que lofoomata, comienza un nuevofoo.Los archivos PID quedan obsoletos. Necesita una lógica demasiado complicada (o debería decir, no trivial) para verificar si el archivo PID está obsoleto y si dicha lógica es nuevamente vulnerable
1..¿Qué sucede si ni siquiera tiene acceso de escritura o está en un entorno de solo lectura?
Es una sobrecomplicación sin sentido; vea cuán simple es mi ejemplo anterior. No hay necesidad de complicar eso, en absoluto.
Ver también: ¿Los archivos PID todavía tienen fallas cuando lo hacen 'bien'?
Por cierto; incluso peor que los archivos PID está analizando
ps! Nunca hagas esto.psEs muy inportable. Si bien lo encuentra en casi todos los sistemas UNIX; sus argumentos varían mucho si desea una salida no estándar. ¡Y la salida estándar es SOLO para consumo humano, no para análisis con secuencias de comandos!psconduce a MUCHOS falsos positivos. ¡Tome elps aux | grep PIDejemplo, y ahora imagine que alguien comienza un proceso con un número en algún lugar como argumento que resulta ser el mismo que el PID con el que miró a su demonio! Imagina a dos personas que comienzan una sesión X y estás buscando X para matar a la tuya. Es todo tipo de cosas malas.Si no desea administrar el proceso usted mismo; Existen algunos sistemas perfectamente buenos que actuarán como monitor de sus procesos. Mira en runit , por ejemplo.
fuente
while true; do myprocess; donepero tenga en cuenta que ahora no hay forma de detener el proceso.trap 'kill $(jobs -p)' EXIT; until myserver & wait; do sleep 1; doneEcha un vistazo a monit ( http://mmonit.com/monit/ ). Maneja el inicio, la detención y el reinicio de su secuencia de comandos y puede realizar comprobaciones de estado y reinicios si es necesario.
O haz un script simple:
fuente
La forma más fácil de hacerlo es usar flock en el archivo. En el script Python que harías
En shell puedes probar si se está ejecutando:
Pero, por supuesto, no tiene que probar, porque si ya se está ejecutando y lo reinicia, saldrá con
'other instance already running'Cuando el proceso muere, todos sus descriptores de archivo se cierran y todos los bloqueos se eliminan automáticamente.
fuente
flock... de hecho, la página del manual demuestra explícitamente cómo.exec {lock_fd}>/tmp/script.lock; flock -x "$lock_fd"es el bash equivalente a su Python, y deja el bloqueo retenido (por lo tanto, si luego ejecuta un proceso, el bloqueo permanecerá retenido hasta que el proceso salga).flockes la forma correcta, pero sus scripts están equivocados. El único comando que debe configurar en crontab es:flock -n /tmp/script.lock -c '/path/to/my/script.py'Debe usar monit, una herramienta estándar de Unix que puede monitorear diferentes cosas en el sistema y reaccionar en consecuencia.
De los documentos: http://mmonit.com/monit/documentation/monit.html#pid_testing
compruebe el proceso checkqueue.py con pidfile /var/run/checkqueue.pid si se cambia pid entonces exec "checkqueue_restart.sh"También puede configurar monit para que le envíe un correo electrónico cuando reinicie.
fuente
fuente
ps ax|grep .... Puede instalarlo o escribir una función para eso: function psgrep () {ps ax | grep -v grep | grep -q "$ 1"}No estoy seguro de cuán portátil es en todos los sistemas operativos, pero puede verificar si su sistema contiene el comando 'run-one', es decir, "man run-one". Específicamente, este conjunto de comandos incluye 'run-one-constantemente', que parece ser exactamente lo que se necesita.
Desde la página del manual:
Nota: obviamente, esto podría llamarse desde su script, pero también elimina la necesidad de tener un script.
fuente
He utilizado el siguiente script con gran éxito en numerosos servidores:
notas:
$INSTALLATIONcontiene suficiente de la ruta del proceso que es totalmente inequívocaEste script se usa para cerrar una instancia en ejecución de tomcat, que quiero cerrar (y esperar) en la línea de comandos, por lo que iniciarlo como un proceso secundario simplemente no es una opción para mí.
fuente
grep | awksigue siendo un antipatrón : deseaawk "/$INSTALLATION/ { print \$1 }"combinar lo inútilgrepen el script Awk, que puede encontrar líneas por expresión regular en sí muy bien, muchas gracias.Lo uso para mi proceso npm
fuente