3 votos

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

Publicando desde unix.SE bajo recomendación.

Tengo un script de bash llamado testing guardado dentro de /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 devuelve como se espera:

TTY        PID  PPID ARGS
ttys000  73674 73673 -bash                              # inicio de sesión usado para ejecutar sudo
ttys000  73701 73674 sudo testing                       # proceso de sudo
ttys000  73702 73701 /bin/bash /usr/local/bin/testing   # script "testing" de bash siendo ejecutado por sudo
ttys001   3714  3713 -bash                              # segundo inicio de sesión usado para generar esta lista de procesos

Sin embargo, después de cerrar la primera ventana de terminal (mientras testing sigue ejecutándose dentro de 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 era de esperar, el primer inicio de sesión ha sido terminado y el segundo inicio de sesión sigue ejecutándose. ¡Pero el proceso de sudo y su hijo bifurcado (ahora huérfano), el script testing, sigue ejecutándose!

Sospecho que esto se debe a que el usuario, no root, es quien cierra la ventana de Terminal, y como tal no tiene los permisos necesarios para afectar los procesos de root. ¿Es esto correcto? Siento que me estoy perdiendo algo básico aquí. ¿Hay alguna forma de permitir que los procesos de root se terminen 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 daemon que sigue ejecutándose hasta que se apaga el sistema. Aquí tienes dos ejemplos simples donde se crean huérfanos. El macOS es High Sierra que usa bash como shell predeterminado.

Si decides repetir los ejemplos, tendrás que reemplazar los ids de proceso con los que obtienes.

Cuando la ventana principal termina, se envía una señal de colgado (SIGHUP) a los procesos hijos. Normalmente, esto hace que cada proceso hijo termine. Sin embargo, si un hijo elige no terminar o nunca recibe una señal de colgado (SIGHUP), entonces el hijo puede convertirse en 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. Se muestra la salida a continuación.

Ú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 colgado (SIGHUP) se ignore. Luego, 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 colgado (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. Observa a continuación.

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

Finalmente, se ingresan los comandos que se muestran 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 colgado (SIGHUP), se utiliza el comando disown %1 para evitar que se envíe una señal de colgado (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. Se muestra la salida a continuación.

Ú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. Otro huérfano ha sido creado.

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 zombi
init
Daemon

0 votos

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

0 votos

El comando sudo envía la señal SIGHUP al script siempre y cuando el remitente sea un usuario root. Básicamente es lo que publicaste en tu pregunta. No puedo reproducir exactamente el ejemplo que mencionas en tu pregunta. Cuando intento cerrar la ventana, no obtengo un proceso huérfano a menos que el script se esté ejecutando en segundo plano.

0 votos

Interesante. No estoy seguro de cuánto importaría, pero mi script es simplemente 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