2011-11-14 14 views
24

Veo una gran cantidad de secuencias de comandos shell que hacer:¿Es necesario especificar trampas que no sean EXIT?

 
trap cmd 0 1 2 3 13 15 # EXIT HUP INT QUIT PIPE TERM 

En todos los depósitos que tienen acceso a por el momento, todas las trampas que no sean 0 son redundantes, y cmd se ejecutará tras la recepción de una señal si la trampa es simplemente especifica:

 
trap cmd 0 

¿es ésta última medida suficiente, o hacer algunas conchas requieren las otras señales que ha de fijar?

Respuesta

15

Para asegurarse de que el manejador de señal EXIT no se ejecutará dos veces (que casi siempre no es lo que desea) siempre debe configurarse para ignorar o restablecer dentro de la definición del manejador de señal EXIT.

Lo mismo vale para las señales que tienen más de un controlador de señal definido para ellas en un programa.

# reset 
trap 'excode=$?; cmd; trap - EXIT; echo $excode' EXIT HUP INT QUIT PIPE TERM 

# ignore 
trap 'excode=$?; trap "" EXIT; cmd; echo $excode' EXIT HUP INT QUIT PIPE TERM 
+0

Esta es una buena idea. No creo que sea necesario preocuparse por señales con más de una trampa definida, ya que solo puede definir una trampa por señal. (La segunda trampa reemplaza a la primera, en lugar de agregarla a una pila.) ¿Algunos proyectiles permiten definir trampas múltiples? –

+2

Estaba bajo la misma confusión que @WilliamPursell hasta que finalmente noté "ignorado ** o ** restablecido". –

13

Creo que la captura 0 se ejecuta justo antes de la terminación del script en todos los casos, por lo que es útil para la funcionalidad de limpieza (como eliminar archivos temporales, etc.). Las otras señales pueden tener un manejo de error especializado, pero deben terminar el script (es decir, salir de la llamada).

Lo que ha descrito, en mi opinión, realmente ejecutaría cmd dos veces. Una vez para la señal (por ejemplo, SIGTERM) y una vez más para la salida (trampa 0).

Creo que la manera correcta de hacer esto es como la siguiente (véase la especificación POSIX para trap):

trap "rm tmpfile" 0 
trap "exit 1" TERM HUP ... 

Esto asegura un archivo temporal se elimina tras la finalización de la escritura, y le permite establecer estados de salida personalizado en señales.

NOTA: se llama a la trampa 0 si se encuentra o no una señal.

Si no está interesado en establecer un estado de salida, la captura 0 sería suficiente.

5

El estándar de shell no especifica si se ejecuta una trampa en 0 cuando se recibe una señal no capturada. En particular, bash y dash se comportan de manera diferente. Dado trap cmd-list 0 sin trampas configuradas para ninguna señal, bash ejecutará la lista cmd al recibir SIGTERM, pero el guión no lo hará. Dado trap cmd-list 0 2, bash ejecuta cmd-list una vez al recibir SIGTERM, y dash ejecuta cmd-list dos veces.

+2

Así que la mejor respuesta es una combinación de éste y Brandon Horsley de: para la portabilidad, no asuma que el 'trampa ... 0' se ejecutará en SIGTERM, y no asuma que ganó 't. Haga una 'trampa' separada salida 1 "SIGTERM ...' para garantizar que así sea. – dubiousjim

Cuestiones relacionadas