GNU/Linux >> Tutoriales Linux >  >> Linux

Bash:¿Por qué la secuencia de comandos principal no termina en SIGINT cuando la secuencia de comandos secundaria atrapa a SIGINT?

Nueva respuesta:

Esta pregunta es mucho más interesante de lo que originalmente sospechaba. La respuesta se da esencialmente aquí:

¿Qué sucede con SIGINT (^C) cuando se envía a un script de perl que contiene elementos secundarios?

Aquí está el dato relevante. Me doy cuenta de que no estás usando Perl, pero supongo que Bash está usando la convención de C.

La función de sistema integrada de Perl funciona igual que la función C system(3) de la biblioteca C estándar en lo que respecta a las señales. en lugar del llamado por él, IGNORARÁ cualquier SIGINT y SIGQUIT mientras los niños se están ejecutando.

Esta explicación es la mejor que he visto sobre las diversas opciones que se pueden tomar. También dice que Bash hace el enfoque WCE. Es decir, cuando un proceso padre recibe SIGINT, espera hasta que regrese su proceso hijo. Si ese proceso manejado salió de un SIGINT, también sale con SIGINT. Si el niño salió de otra manera, ignora SIGINT.

También hay una forma en que el shell que llama puede saber si el programa llamado salió en SIGINT y si ignoró SIGINT (o lo usó para otros fines). Al igual que en la forma WUE, el shell espera a que el hijo se complete. Calcula si el programa finalizó en SIGINT y, de ser así, interrumpe el script. Si el programa hizo alguna otra salida, el script continuará. Llamaré a la forma de hacer las cosas "WCE" (por "espera y salida cooperativa") para el resto de este documento.

No puedo encontrar una referencia a esto en la página de manual de Bash, pero seguiré buscando en los documentos de información. Pero estoy 99 % seguro de que esta es la respuesta correcta.

Respuesta anterior:

Un estado de salida distinto de cero de un comando en un script Bash no finaliza el programa. Si haces un echo $? después de ./script2.sh mostrará 130. Puede terminar el script usando set -e como sugiere phs.

$ help set
...
-e  Exit immediately if a command exits with a non-zero status.

La segunda parte de la respuesta actualizada de @seanmcl es correcta y el enlace a http://www.cons.org/cracauer/sigint.html es realmente bueno para leer detenidamente.

Desde ese enlace, "No puede 'falsificar' el estado de salida correcto mediante una salida (3) con un valor numérico especial, incluso si busca el valor numérico para su sistema ". De hecho, eso es lo que se intenta en el script2.sh de @Hermann Speiche.

Una respuesta es modificar el controlador de función en script2.sh de la siguiente manera:

function handler {
  # ... do stuff ...
  trap INT
  kill -2 $$
}

Esto elimina efectivamente el controlador de señal y "vuelve a lanzar" el SIGINT, lo que hace que el proceso bash salga con las banderas apropiadas, de modo que su proceso bash padre maneje correctamente el SIGINT que se le envió originalmente. De esta manera, usando set -e o cualquier otro truco no es realmente necesario.

También vale la pena señalar que si tiene un ejecutable que se comporta incorrectamente cuando se envía un SIGINT (no se ajusta a "Cómo ser un programa adecuado" en el enlace anterior, por ejemplo, sale con un código de retorno normal), una forma de solucionar esto es ajustar la llamada a ese proceso con un script como el siguiente:

#!/bin/bash

function handler {
  trap INT
  kill -2 $$
}

trap handler INT
badprocess "[email protected]"

Linux
  1. ¿Por qué el Pgid de los procesos secundarios no es el Pid del padre?

  2. ¿Por qué la sustitución del proceso Bash no funciona con algunos comandos?

  3. ¿Por qué el script de Bash no se cierra después de la ejecución?

  4. ¿Por qué no puedo usar Cd en un script Bash?

  5. ¿El comando Rm en Bash Script no funciona con variables?

¿Por qué `exit &` no funciona?

Cualquier forma de salir del script bash, pero sin salir de la terminal

Generar error en un script Bash

La coincidencia de patrones no funciona en el script bash

¿Por qué mi $LD_LIBRARY_PATH se desarma cuando uso screen con bash?

¿Por qué no sale un ciclo bash while cuando se conecta a un subcomando terminado?