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

25

J'ai besoin de démonter quelque chose dans mon script, mais parfois il est démonté 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 "blocage", 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 sudo umount mountsoit 0, ce qui signifie qu'il a été démonté avec succès?

charliehorse55
la source

Réponses:

59

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

Parce umountque rien ne sort sur sa sortie standard (les erreurs vont à stderr), se `sudo umount mount`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é [et ]renvoie false (un état de sortie différent de zéro), vous n'entrerez donc pas dans la boucle.

Même s'il umountavait 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 la umountsortie d'une erreur ou d'un avertissement sur son stderr, c'est là que cela [aurait pu être utile. Le -n "some-string"est une expression conditionnelle reconnue par la [commande pour vérifier 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 umount commande nous dit 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 cela umountpeut échouer car le répertoire n'est pas monté et que 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
Stéphane Chazelas
la source
Fonctionne, génial!
charliehorse55
1
+1 pour expliquer la différence entre l' utilisation [, [[ou non. Je souhaite que des pages de manuel typiques, des exemples GNU et / ou TLDP sur les conditions bash couvrent un tel détail
renoirb
5

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

christopher barry
la source
1
[[...]]est ksh/ bash/ zshspécifique, qui ont tous la $SECONDSvariable spéciale, vous pouvez donc faire:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas
Gardez à l'esprit qu'une mount remount,rocommande sur un appareil mips anno 2009 avec une clé USB Intenso Micro Line peut prendre 23 voire 30 secondes .
Pro Backup du