Attendre l'utilisation des commandes sous 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

Je m'attendais successà un statut de sortie lorsque j'envoie 0, mais j'obtiens toujours failure.

De plus, waitn'attend pas 300 secondes. Au lieu de cela, je reçois le message immédiatement. Je suppose que $!c'est l'enfant immédiat de $$mon script. N'est-ce pas?

Est-il possible de capturer l'état de sortie d'attente comme exit_status=$(wait $!)?

if ! ((exit_status));then
    echo sucess
else
    failure
fi
munish
la source

Réponses:

20

Le problème est que vous émettez waiten sous-shell:

if `wait $!`;then

Parce que waitc'est une commande intégrée, pas une commande, elle fonctionne sur le sous - shell , pas sur votre shell actuel.

La sortie que vous verriez mais que vous ne voyez pas est:

wait: pid 12344 is not a child of this shell

... avec un statut de retour de 1.

Pour effectuer votre test, vous devrez le faire sans utiliser de sous-coque.

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

wait $b && echo success || echo failure

Cela donne le résultat que vous attendez et attend aussi longtemps que vous vous attendez:

$ 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

Vous pouvez vérifier l'état de sortie de n'importe quelle commande avec $?:

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

Il y a eu quelques autres erreurs dans votre script. Votre #!ligne était mal formée, ce que j'ai corrigé. Vous attribuez $!à $b, mais n'utilisez pas $b.

bahamat
la source
12

Retirez les contre-coups.

En l'état, vous exécutez waitdans un sous-shell, qui n'a pas accès aux travaux du shell parent, il échouera donc immédiatement.


Si vous voulez l'état de sortie, obtenez la valeur de $?immédiatement après l'attente.

command_here &
wait
status=$?
Patrick
la source
2

La suppression des backticks fera fonctionner le programme, mais pas entièrement pour les raisons déjà identifiées. Il est vrai que cela waitéchoue immédiatement car il s'exécute dans un sous-shell et ne peut pas accéder aux processus de son parent, mais le programme ne s'exécutera pas comme prévu même si vous avez utilisé une commande qui a fonctionné.

L' ifinstruction exécute un programme et vérifie si son état de sortie est zéro ou non nul. Lorsque vous utilisez des raccourcis, l'instruction if prendra la sortie du processus, essayez de l'exécuter en tant que programme, puis utilisez le code de sortie pour ce processus. Le programme waitn'échoue donc pas parce qu'il échoue, mais il échoue parce waitqu'il ne produit aucune sortie.

Vous pouvez faire fonctionner le script en utilisant echoà l'intérieur des backticks:

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

Ou supprimez simplement les contre-coups; plus facile pour tout le monde.

Joni
la source