Aguarde o uso do comando no Linux?

16
#!/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 esperava o successstatus de saída quando envio 0, mas ainda estou recebendo failure.

Além disso, waitnão aguarde 300 segundos. Em vez disso, recebo a mensagem imediatamente. Suponho que $!seja o filho imediato de $$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
munish
fonte

Respostas:

20

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

if `wait $!`;then

Porque waité um builtin, não um comando, 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 1.

Para executar seu teste, você precisará fazer isso 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 que você espera 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 estava malformada, que eu consertei. Você atribui $!a $b, mas não usa $b.

bahamat
fonte
12

Retire as costas.

Como está, você está executando waitem um subshell, que não tem acesso aos trabalhos do shell pai, portanto falhará imediatamente.


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

command_here &
wait
status=$?
Patrick
fonte
2

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

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

Você pode fazer o script funcionar usando echodentro dos backticks:

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

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

Joni
fonte