3 votos

Cerrar la ventana de Terminal no mata el script ejecutado con sudo

Publicando desde unix.SE por recomendación.

Tengo un script de bash llamado testing guardado en /usr/local/bin.

En una ventana de terminal en macOS ejecuto sudo testing. En una segunda ventana de terminal, genero una lista de procesos:

ps -axo tty,pid,ppid,args | { head -1; grep "bash\|testing" | grep -v grep; }

Lo cual retorna como se espera:

TTY        PID  PPID ARGS
ttys000  73674 73673 -bash                              # shell de inicio usado para correr sudo
ttys000  73701 73674 sudo testing                       # proceso de sudo
ttys000  73702 73701 /bin/bash /usr/local/bin/testing   # script de bash "testing" siendo ejecutado por sudo
ttys001   3714  3713 -bash                              # segunda shell de inicio usada para generar esta lista de procesos

Sin embargo, después de cerrar la primera ventana de terminal (mientras testing todavía está corriendo en ella), la lista de procesos se ve así:

TTY        PID  PPID ARGS
??       73701     1 sudo testing
??       73702 73701 /bin/bash /usr/local/bin/testing
ttys001   3714  3713 -bash

Como se esperaba, la primera shell de inicio ha sido terminada y la segunda shell de inicio todavía está corriendo. ¡Pero el proceso de sudo y su hijo bifurcado (ahora huerfano), el script testing, todavía están corriendo!

Sospecho que esto se debe a que el usuario, no root, es quien está cerrando la ventana de terminal, y por lo tanto no tiene los permisos necesarios para afectar procesos de root. ¿Es esto correcto? Siento que me estoy perdiendo algo básico aquí. ¿Hay alguna manera de permitir que los procesos de root sean terminados al cerrar la ventana de terminal?

3voto

David Anderson Puntos 2189

Estás hablando de procesos huérfanos. Como verás, tu pregunta tiene poco que ver con sudo. Los huérfanos se asignan al proceso 1. Este proceso 1 se llama init y es un proceso demonio que continúa en ejecución hasta que se apaga el sistema. Aquí hay dos ejemplos simples donde se crean huérfanos. En MacOS High Sierra se utiliza bash como el shell predeterminado.

Si decides repetir los ejemplos, tendrás que reemplazar los ids de procesos con los que obtengas.

Cuando la ventana padre termina, se envía una señal de cierre (SIGHUP) a los procesos hijos. Normalmente, esto provoca que cada proceso hijo termine. Sin embargo, si un hijo elige no terminar o nunca se le envía una señal de cierre (SIGHUP), entonces el hijo puede convertirse en un huérfano.

Ejemplo 1

Abre una nueva ventana de Terminal e ingresa el comando shopt -s huponexit. Este comando es necesario porque bash es un shell de inicio de sesión. A continuación se muestra la salida.

Último inicio de sesión: Jue Mar 12 17:02:31 en ttys008
Marlin:~ davidanderson$ shopt -s huponexit
Marlin:~ davidanderson$

Ingresa el comando { trap '' hup; sleep 60000; } &, como se muestra a continuación.

Marlin:~ davidanderson$ { trap '' hup; sleep 60000; } &
[1] 8993
Marlin:~ davidanderson$

Aquí se crea un nuevo proceso 8993 como trabajo 1. El comando trap '' hup hace que la señal de cierre (SIGHUP) se ignore. A continuación, abre otra ventana de Terminal e ingresa el comando ps -axo tty,pid,ppid,args 8993, como se muestra a continuación.

Último inicio de sesión: Jue Mar 12 17:09:12 en ttys008
Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 8993
TTY        PID  PPID ARGS
ttys008   8993  8972 -bash
Marlin:~ davidanderson$ 

Esto muestra que la primera ventana se le asignó ttys008 y tiene un id de proceso de 8972. Luego, se cierra la primera ventana. En la ventana emergente, se selecciona Terminar. Se envía una señal de cierre (SIGHUP) al proceso 8972, que se ignora. El proceso 8972 ahora es huérfano y se le asignará al proceso 1. Al repetir el comando ps -axo tty,pid,ppid,args 8993 en la segunda ventana, se mostrará esto. Mira abajo.

Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 8993
TTY        PID  PPID ARGS
??        8993     1 -bash
Marlin:~ davidanderson$

Finalmente, se ingresan los comandos mostrados a continuación para enviar una señal de terminal (SIGTERM) al proceso 8993 y mostrar que el proceso ha terminado.

Marlin:~ davidanderson$ kill 8993
Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 8993
TTY        PID  PPID ARGS
Marlin:~ davidanderson$

Ejemplo 2

Esto es básicamente lo mismo que el ejemplo 1, excepto que en lugar de hacer que el proceso ignore la señal de cierre (SIGHUP), se utiliza el comando disown %1 para evitar que se envíe una señal de cierre (SIGHUP) al proceso. Abre una nueva ventana de Terminal e ingresa el comando shopt -s huponexit. Este comando es necesario porque bash es un shell de inicio de sesión. A continuación se muestra la salida.

Último inicio de sesión: Jue Mar 12 17:02:31 en ttys008
Marlin:~ davidanderson$ shopt -s huponexit
Marlin:~ davidanderson$

Luego, ingresa sleep 60000 & seguido de disown %1. El parámetro %1 representa el trabajo 1. Los resultados se muestran a continuación.

Último inicio de sesión: Jue Mar 12 17:14:54 en ttys010
Marlin:~ davidanderson$ sleep 60000 &
[1] 9139
Marlin:~ davidanderson$ disown %1
Marlin:~ davidanderson$

En la segunda ventana, ingresa ps -axo tty,pid,ppid,args 9139. Los resultados se muestran a continuación.

Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 9139
TTY        PID  PPID ARGS
ttys008   9139  9130 sleep 60000
Marlin:~ davidanderson$

Después de cerrar la tercera ventana, ingresa ps -axo tty,pid,ppid,args 9139 en la segunda ventana. Los resultados se muestran a continuación. Se ha creado otro huérfano.

Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 9139
TTY        PID  PPID ARGS
??        9139     1 sleep 60000
Marlin:~ davidanderson$ 

Finalmente, ingresa kill 9139 y ps -axo tty,pid,ppid,args 9139, como se muestra a continuación.

Marlin:~ davidanderson$ kill 9139
Marlin:~ davidanderson$ ps -axo tty,pid,ppid,args 9139
TTY        PID  PPID ARGS
Marlin:~ davidanderson$ 

Referencias

Proceso huérfano
Proceso zombie
init
Demonio

0 votos

¡Muchas gracias por la explicación increíblemente detallada! Parece ser que además de trap '' hup y disown, los comandos sudo también ignorarán SIGHUP. ¿Hay alguna forma en la que pueda matar el proceso de sudo cerrando la ventana de Terminal?

0 votos

El comando sudo pasa la señal SIGHUP al script proporcionado si el remitente es un usuario root. Básicamente es lo mismo que has publicado en tu pregunta. No puedo reproducir exactamente el ejemplo que has publicado en tu pregunta. Cuando intento cerrar la ventana, no obtengo un proceso huérfano a menos que el script esté corriendo en el fondo.

0 votos

Interesante. No estoy seguro de cuánto importaría, pero mi script es solo un bucle while true; do ..., y lo he probado tanto en macOS 10.14 como en 10.13 con el mismo resultado.

AppleAyuda.com

AppleAyuda es una comunidad de usuarios de los productos de Apple en la que puedes resolver tus problemas y dudas.
Puedes consultar las preguntas de otros usuarios, hacer tus propias preguntas o resolver las de los demás.

Powered by:

X