¿El script de Bash no ve SIGHUP?


11

Tengo el siguiente script:

#!/bin/bash
echo "We are $$"
trap "echo HUP" SIGHUP
cat    # wait indefinitely

Cuando envío SIGHUP(usando kill -HUP pid), no pasa nada.

Si cambio ligeramente el script:

#!/bin/bash
echo "We are $$"
trap "kill -- -$BASHPID" EXIT    # add this
trap "echo HUP" SIGHUP
cat    # wait indefinitely

... entonces el script hace echo HUPlo correcto al salir (cuando presiono Ctrl + C):

roger@roger-pc:~ $ ./hupper.sh 
We are 6233
^CHUP

¿Que esta pasando? ¿Cómo debo enviar una señal (no necesariamente tiene que ser SIGHUP) a este script?


44
La señal se entregará y el controlador de señal se ejecutará cuando catfinalice el proceso. Pruebe su secuencia de comandos original y presione Ctrl+Dpara que catsalga el proceso. Mientras el catproceso está en primer plano, HUPno se actúa sobre la señal. Intente nuevamente con catreemplazado por read(un shell incorporado).
— Kusalananda

Perfecto. ¿Alguien quiere convertir eso en una respuesta?
— Roger Lipscombe

Sé que funciona de esa manera, pero dejaré que alguien que tenga más información que yo sepa por qué y por qué responden.
— Kusalananda

Lo utilicé while true; do read; doneal final, de lo contrario, ingresar texto hace que se cierre también, y quiero que se cierre en Ctrl + C.
— Roger Lipscombe

Respuestas:


21

El manual de Bash dice:

Si bash está esperando que se complete un comando y recibe una señal para la cual se ha establecido una trampa, la trampa no se ejecutará hasta que se complete el comando.

Eso significa que a pesar de que la señal se recibe bashcuando la envía, su trampa en SIGHUP solo se llamará cuando catfinalice.

Si este comportamiento no es deseable, use bashbuiltins (por ejemplo, read+ printfen un bucle en lugar de cat) o use trabajos en segundo plano (consulte la respuesta de Stéphane ).


9

@xhienne ya ha explicado por qué , pero si desea que la señal actúe de inmediato (y no salir del script), puede cambiar su código a:

#! /bin/bash -
interrupted=true
trap 'interrupted=true; echo HUP' HUP

{ cat <&3 3<&- & pid=$!; } 3<&0

while
  wait "$pid"
  ret=$?
  "$interrupted"
do
  interrupted=false
done
exit "$ret"

El pequeño baile con los descriptores de archivo es evitar el hecho de que bashredirige stdin a los /dev/nullcomandos iniciados en segundo plano.


¿Funciona esto porque el bloque de código se ejecuta en una subshell?
— Pysis
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.