Aguarde o uso do comando no Linux?

14
#!/bin/bash
function back()
{
    sleep $1
    exit $2
}
back $1 $2 &
b=$!
if 'wait $!';then
    echo success
else
    echo failure
fi
bash-3.00# ./back 300 0
failure
bash-3.00# ./back 300 1
failure

Eu estava esperando success como status de saída quando eu enviar 0, mas ainda estou recebendo failure .

Além disso, wait não espera por 300 segundos. Em vez disso, recebo a mensagem imediatamente. Eu assumo $! é o filho imediato de $$ no meu script. Não é?

É possível capturar o status de saída de espera como exit_status=$(wait $!) ?

if ! ((exit_status));then
    echo sucess
else
    failure
fi
    
por munish 26.09.2013 / 06:11

3 respostas

19

O problema é que você está emitindo wait em um subshell:

if 'wait $!';then

Como wait é um comando interno, não um comando, ele está operando no subshell , não no seu shell atual.

A saída que você veria, mas não é, é:

wait: pid 12344 is not a child of this shell

... com um status de retorno de 1.

Para realizar seu teste, você precisará fazê-lo sem usar um subshell.

#!/bin/bash
function back()
{
  sleep $1
  exit $2
}
back $1 $2 &
b=$!

wait $b && echo success || echo failure

Isso fornece o resultado esperado e aguarda o tempo que você espera:

$ time ./test.sh 3 0
success
./test.sh 3 0  0.00s user 0.01s system 0% cpu 3.012 total
$ time ./test.sh 3 1
failure
./test.sh 3 1  0.00s user 0.01s system 0% cpu 3.012 total

Você pode verificar o status de saída de qualquer comando com $? :

$ /bin/true
$ echo $?
0
$ /bin/false
$ echo $?
1

Houve alguns outros erros no seu script. Sua linha #! foi malformada, o que corrigi. Você atribui $! a $b , mas não use $b .

    
por 26.09.2013 / 06:37
11

Remova os backticks.

Como está, você está executando wait em um subshell, que não tem acesso aos jobs do shell pai, então ele falhará imediatamente.

Se você quiser o status de saída, obtenha o valor de $? imediatamente após a espera.

command_here &
wait
status=$?
    
por 26.09.2013 / 06:34
2

Remover os backticks fará o programa funcionar, mas não inteiramente por causa dos motivos já identificados. É verdade que wait falha imediatamente porque é executado em uma subshell e não pode acessar os processos de seus pais, mas o programa não seria executado como esperado, mesmo se você usasse um comando que funcionasse.

A instrução if executa um programa e verifica se seu status de saída é zero ou diferente de zero. Quando você usa backticks, a instrução if pegará a saída do processo, tentará executá-la como um programa e, em seguida, usará o código de saída para esse processo. Portanto, o programa não está falhando porque wait falha, mas falha porque wait não produz saída.

Você pode fazer o script funcionar usando echo dentro dos backticks:

if 'echo wait $!'; then
    echo success
else
    echo failure
fi

Ou apenas remova os backticks; mais fácil para todos.

    
por 26.09.2013 / 09:04