Você pode especificar um trap separado em um subshell criado com ()?

1

Estou escrevendo um script que inicia um subshell para fazer algum trabalho. Em um caso especial, o script precisa dizer ao subshell para parar o que está fazendo e sair mais cedo. No entanto, meu código de psuedo abaixo não parece estar funcionando. Estou tentando o impossível? É possível definir uma armadilha separada para sinais em um subshell?

#!/bin/bash

function myExitFunction { ... }
trap myExitFunction SIGTERM

while [ 1 ] ; do
    waitForSpecialCondition

    kill -0 $SUBSHELL_PID   # check if subshell is running
    if [ $? -eq 0 ] ; then  # and kill it if it is
        kill $SUBSHELL_PID
    fi

    (
    someProcess
    MYOWNCHILD=$!           # save someProcess's pid to kill later if I need to
    trap "kill $MYOWNCHILD" SIGTERM
    ... # do stuff
    ) &
    SUBSHELL_PID=$!

done
    
por Cory Klein 24.05.2011 / 21:57

1 resposta

2

Acontece que meu problema não era o que eu realmente achava que era. Abaixo está um script que se comporta como o código psuedo acima. Ele funciona exatamente como eu esperava (embora um pouco inventado para ser simples), e é um bom exemplo de ter traps de sinal separados para um processo de shell pai e filho.

Esta funcionalidade de armadilha pode ser demonstrada apenas executando o script e saindo por um ctrl-c.

#!/bin/bash

function endEarly {
echo "Terminating early"
if [ ! -z $SUBSHELL_PID ] ; then
    echo "Killing subshell with pid $SUBSHELL_PID"
    kill $SUBSHELL_PID
fi
exit
}

trap endEarly SIGTERM SIGINT

echo "Give me some input"
while [ 1 ] ; do
    read INPUT

    # kill the subshell if it exists and is running
    if [ ! -z $SUBSHELL_PID ] ; then
        kill -0 $SUBSHELL_PID
        if [ $? -eq 0 ] ; then
            kill $SUBSHELL_PID
        fi
    fi

    echo "Now I'll repeat your input.  Feel free to change it"
    echo "at any time by typing it again and hitting <Enter>"
    {
        (
            while [ 1 ] ; do
                echo "$INPUT"
                sleep 5
            done
        ) &
        CHILD_PID=$!
        trap "kill $CHILD_PID;" SIGTERM SIGINT
        wait $CHILD_PID
    } &
    SUBSHELL_PID=$!
done
    
por 24.05.2011 / 22:41