enviar señal a la tubería de command derriba toda la tubería

Tengo un ejemplo simple de dos processs

el primero es un bucle simple que hace algún procesamiento

#!/bin/bash function signalHandler() { echo "sig: $1 received ==> exit" for i in {1..5}; do echo "cleanup $i %" sleep 1 done trap SIGINT kill -INT $$ } trap signalHandler SIGUSR2 for i in {1..100000}; do echo "doing stuff $i %" sleep 0.1 done 

Lancé el script así:

 ./script.sh | grep "wow" 

donde adjunté un command grep auxiliar solo para demostración.

Cuando envío una señal USR2 al process grep ( kill USR2 $(pgrep grep) ), todo el tubo se derriba (?). ¿Por qué script.sh no continúa?

En segundo lugar, cuando envío una señal USR2 a todo el grupo de processs (algo así como kill USR2 -$! ), Obviamente sucede lo mismo, ya que grep cierra rápidamente, script.sh todo el process sin permitir que script.sh ejecute signalHandler . Creo que tengo un malentendido sobre cómo debería funcionar eso.

Muchas gracias

Solutions Collecting From Web of "enviar señal a la tubería de command derriba toda la tubería"

Como comentó @muru, el problema es que su script no maneja SIGPIPE .

Los siguientes cambios permitirán que el script finalice según lo previsto:

 function signalHandler() { echo "sig: $1 received ==> exit" >&2 # <-- for i in {1..5}; do echo "cleanup $i %" >&2 # <-- sleep 1 done trap SIGINT kill -INT $$ } trap signalHandler SIGUSR2 trap signalHandler SIGPIPE # <-- 

Para mantener el ejemplo simple, se usa el mismo manejador de señal para manejar SIGPIPE . La salida de echo del manejador de señal se networkingirige a STDERR , ya que obviamente STDOUT ya está roto en el momento en que el SIGPIPE queda atrapado.

Salida:

 $ ./script.sh | grep wow ./script.sh: line 16: echo: write error: Broken pipe sig: received ==> exit cleanup 1 % cleanup 2 % cleanup 3 % cleanup 4 % cleanup 5 % User defined signal 2: 31 

La tubería se rompe (primer post de error), pero el manejador de señales se completa antes de que salga script.sh .

Si desea ignorar por completo el SIGPIPE , deberá agregar un controller ficticio para la señal y networkingireccionar STDERR para la instrucción de echo principal a /dev/null :

 function signalHandler2() { : } trap signalHandler SIGUSR2 trap signalHandler2 SIGPIPE # ...skip... for i in {1..100000}; do echo "doing stuff $i %" 2>/dev/null