web-dev-qa-db-fra.com

Script Bash - boucle jusqu'à ce que la valeur de retour soit 0

J'ai besoin de démonter quelque chose dans mon script, mais parfois il se démonte avant que toutes les données aient fini d'être copiées et provoquent l'échec du démontage. J'ai cherché un moyen de faire un umount "bloquant", mais je n'ai rien trouvé. J'ai donc essayé d'écrire un script à boucler jusqu'à ce qu'il puisse être démonté, mais cela ne fonctionne pas.

while [ `Sudo umount mount` ]
do
    sleep 0.1
done
rmdir mount

Lors de l'exécution des sorties:

umount: /home/evantandersen/mount: device is busy.
        (In some cases useful info about processes that use
         the device is found by lsof(8) or fuser(1))
rmdir: failed to remove `mount': Device or resource busy

Ne devrait-il pas boucler jusqu'à ce que la valeur de retour de Sudo umount mount est 0, ce qui signifie qu'il a été démonté avec succès?

25
charliehorse55

La commande [ Sert à évaluer les expressions conditionnelles. C'est inutile ici.

Parce que umount ne produit rien sur sa sortie standard (les erreurs vont à stderr), `Sudo umount mount` Se développe à rien.

C'est donc comme:

while [ ]
do
  sleep 0.1
done

La commande [, Lorsqu'elle n'est passée aucun argument à côté de [ Et ] Renvoie faux (un état de sortie différent de zéro), donc vous ne entrez dans la boucle.

Même si umount avait généré ses erreurs sur stdout, l'utilisation de la commande [ N'aurait pas eu de sens, car les mots résultant de cette sortie n'auraient jamais constitué une expression conditionnelle valide.

Ici vous voulez:

until Sudo umount mount
do
  sleep 0.1
done

Autrement dit, vous voulez vérifier l'état de sortie de Sudo/umount, pas d'une commande [.

Si vous vouliez vérifier si umount produisait une erreur ou un avertissement sur son stderr, c'est là que [ Aurait pu être utile. Le -n "some-string" Est une expression conditionnelle reconnue par la commande [ Pour tester si "some-string" Est vide ou non, donc quelque chose comme:

while [ -n "$(Sudo umount mount 2>&1 > /dev/null)" ]; do
  sleep 0.1
done

Mais rechercher la présence de messages d'erreur ou d'avertissement est généralement une mauvaise idée. La commande umount nous indique si elle réussit ou non avec son code de sortie, c'est beaucoup plus fiable. Il pourrait réussir et afficher un message d'avertissement. Il pourrait échouer et ne pas générer d'erreur (comme lorsqu'il est tué).

Dans ce cas particulier, notez que umount peut échouer car le répertoire n'est pas monté, et vous boucleriez pour toujours dans ce cas, vous pouvez donc essayer une autre approche comme:

while mountpoint -q mount && ! Sudo umount mount; do
  sleep 0.1
done

Ou si "mount" peut être monté plusieurs fois et que vous souhaitez tous les démonter:

while mountpoint -q mount; do
  Sudo umount mount || sleep 0.1
done
59

fonction réutilisable et expirera en 'n' secondes

_umount() {
    [[ $# -lt 2 ]] && { 
        echo "Usage: ${FUNCNAME} <timeout_secs> <mnt_point>"; return 1
    }
    timeout=$(($(date +%s) + ${1}))
    until umount "${2}" 2>/dev/null || [[ $(date +%s) -gt $timeout ]]; do
       :
    done
}

pas besoin de dormir

5