¿Quieres mejorar esta pregunta? Agrega detalles y aclara el problema editando esta publicación.
Cerrado hace 3 años.
Mejorar esta pregunta
Para entender
Si Bash está esperando que se complete un comando y recibe una señal para
que se ha establecido una trampa, la trampa no se ejecutará hasta que se complete el comando
.
Cuando Bash está esperando un comando asíncrono a través de la espera incorporada ,
la recepción de una señal para la que se ha establecido una trampa hará que la
espera interna vuelva inmediatamente con un estado de salida superior a
128, inmediatamente después de lo cual se ejecuta la trampa.
del manual de Bash,
ejecuto lo siguiente:
-
En mis dos ejemplos, SIGINT (enviado con Ctrl-C) termina un trabajo en primer plano
(el primer caso en la cita) y un trabajo en segundo plano
(el segundo caso en la cita) ambos inmediatamente, sin esperar para
que lo completen.¿Significa la primera oración de la cita que si Bash está ejecutando un
trabajo en primer plano y recibe la señalSIGINT, la trampa de la señalSIGINT, cuando se establece, se ejecutará hasta que se complete el comando?
En caso afirmativo, por qué en mi primer ejemplo,ctrl-Chacer que el trabajo en primer plano
exista inmediatamente antes de que pueda completarse?$ sleep 10000 # a foreground job ^C $ sleep 10000 & # a background job [1] 21219 $ wait 21219 ^C $ echo $? 130 -
¿Qué significa “una señal para la que se ha tendido una trampa” decir,
-
una señal
argcuya trampa se ha especificado a través detrap arg sigspec, o -
una señal que no se ignora, o
-
¿una señal cuya trampa no es la predeterminada?
En los ejemplos de mi parte 1, no configuré una trampa para SIGINT, por lo que la señal tiene su
controlador predeterminado (que sale de cualquier ciclo de ejecución). Es una
señal que tiene su controlador predeterminado considerado tener una trampa que se ha
tendido? -
-
Puse una trampa para
SIGINT, peroctrl-Chará que el siguiente comando
salga antes de completarse. Entonces, ¿es contrario a la primera
oración de mi cita?$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $Antes de tenderle la trampa a
SIGINT,ctrl-Ctambién hará que el mismo comando
salga antes de completarse. Entonces, ¿es contrario a la primera
oración de mi cita?$ bash -c 'sleep 10; echo "$?"' ^C -
¿Podría dar algunos ejemplos para explicar qué significan las dos oraciones en
la cita?
Gracias.
Respuesta aceptada:
¿Qué significa "una señal para la que se ha tendido una trampa"?
Esa es una señal para la que se ha definido un controlador (con trap 'handling code' SIG ) donde el código de manejo no está vacío, ya que eso haría que se ignorara la señal.
Por lo tanto, las señales que tienen su disposición predeterminada no son señales para las que se ha establecido una trampa.
Parte de esa cita en su publicación también se aplica a las señales que tienen su disposición predeterminada, aunque obviamente no es la parte sobre ejecutar el trampa , ya que no se han definido trampas para ellos.
El manual habla sobre la entrega de señales al shell , no a los comandos que ejecuta desde ese shell.
1.
Si Bash está esperando que se complete un comando y recibe una señal para la que se ha establecido una trampa, la trampa no se ejecutará hasta que se complete el comando.
(1)
por qué en mi primer ejemplo, ctrl-C hace que el trabajo en primer plano salga inmediatamente antes de que pueda completarse
Si ejecuta sleep 10 en el indicador de un shell interactivo , el shell pondrá ese trabajo en primer plano (a través de un ioctl() en el dispositivo tty que le dice a la disciplina de la línea terminal qué grupo de procesos es el de primer plano), por lo que solo sleep obtendrá un SIGINT en ^C y el caparazón interactivo no , por lo que no es útil probar ese comportamiento.
-
El shell principal, ya que es interactivo, no recibirá el SIGINT ya que su proceso no está en el grupo de procesos de primer plano.
-
Cada comando es libre de manejar las señales como les plazca.
sleepno hace nada especialmente con SIGINT, por lo que obtendrá la disposición predeterminada (terminar) a menos que se haya ignorado SIGINT al inicio.
(2) Si ejecuta sleep 10 en un shell no interactivo ,
bash -c 'sleep 10; echo "$?"'
Tanto el bash no interactivo shell y sleep recibirá el SIGINT cuando presione Ctrl-C.
Si bash salió de inmediato, podría dejar el sleep comando que se ejecuta desatendido en segundo plano si ignora o maneja la señal SIGINT. Entonces, en cambio,
bashcomo la mayoría de las otras conchas, bloques la recepción de señales (al menos algunas señales) cuando se esperan órdenes.- La entrega se reanuda después de que finaliza el comando (sobre lo cual se ejecutan las trampas). Eso también evita que los comandos en trampas se ejecuten simultáneamente con otros comandos.
En ese ejemplo anterior, sleep morirá con SIGINT, así que bash no tiene que esperar mucho para manejar su propio SIGINT (aquí para morir ya que no agregué una trap en SIGINT).
(3) cuando presiona Ctrl+C mientras ejecuta el shell no interactivo:
bash -c 'sh -c "trap "" INT; sleep 3"; echo "$?"'
(sin trap en SIGINT) bash no es asesinado por el SIGINT. bash , como algunos otros shells, tratan SIGINT y SIGQUIT de manera especial. Implementan la espera y salida cooperativa comportamiento descrito en https://www.cons.org/cracauer/sigint.html (y se sabe que causa algunas molestias como los scripts que llaman a SIGINT que maneja comandos que no se pueden interrumpir con ^C )
(4) Para probar correctamente, debe ejecutar un bash no interactivo que tiene una trampa SIGINT configurada y llama a un comando que no muere de inmediato en SIGINT como:
bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 3"'
bash está esperando a sh que tiene (junto con sleep ) SIGINT ignorado (debido a la trap "" INT ), por lo que SIGINT no eliminará sleep ni sh . bash no ignora SIGINT, pero su manejo se difiere hasta sh devoluciones. Ves Ouch siendo mostrado, no sobre Ctrl+C , pero después de sleep y sh han terminado normalmente.
Tenga en cuenta que la trap El comando establece una trampa para una señal para el mismo shell en el que se ejecuta. Así que cuando la trap el comando se ejecuta fuera del shell no interactivo y en el shell principal,
$ trap "echo You hit control-C!" INT $ bash -c 'sleep 10; echo "$?"' ^C $
el bash no interactivo y sleep los comandos no heredarán esa trap del caparazón principal. Los controladores de señales se pierden al ejecutar un comando diferente (execve() borra todo el espacio de direcciones del proceso, incluido el código del controlador). Al execve() , las señales que tenían un controlador definido vuelven a la disposición predeterminada, las que se ignoraron permanecen ignoradas.
Además de eso, en la mayoría de los shells, trap s también se restablecen en subcapas.
2.
Cuando Bash está esperando un comando asíncrono a través de la espera incorporada , la recepción de una señal para la que se ha configurado una trampa hará que la espera interna vuelva inmediatamente con un estado de salida superior a 128, inmediatamente después de lo cual se ejecuta la trampa.
Al usar wait explícitamente , wait es interrumpido por cualquier señal que tenga una trampa configurada (y obviamente también aquellas que matan el caparazón por completo).
Eso hace que sea difícil obtener el estado de salida de un comando de manera confiable cuando hay señales atrapadas :
$ bash -c 'trap "echo Ouch" INT; sh -c "trap "" INT; sleep 10" & wait "$!"; echo "$?"'
^COuch
130
En ese caso, sleep y sh no fueron asesinados por SIGINT (ya que lo ignoran). Todavía wait regresa con un 130 estado de salida porque se recibió una señal (SIGINT) mientras esperaba sh . Tendrías que repetir el wait "$!" hasta sh realmente termina para obtener sh estado de salida.