Bash Scripting - Schleife, bis der Rückgabewert 0 ist

25

Ich muss etwas in meinem Skript ummounten, aber manchmal wird das Ummounten abgebrochen, bevor alle Daten fertig kopiert wurden und das Ummounten fehlschlägt. Ich habe nach einer Möglichkeit gesucht, ein "Blocking" -Umount durchzuführen, aber ich habe nichts gefunden. Also habe ich versucht, ein Skript für eine Schleife zu schreiben, bis es nicht mehr bereitgestellt werden konnte, aber es funktioniert nicht.

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

Beim Ausführen von Ausgaben:

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

Sollte es nicht eine Schleife sudo umount mountausführen, bis der Rückgabewert 0 ist, was bedeutet, dass es erfolgreich umountet wurde?

charliehorse55
quelle

Antworten:

59

Der [Befehl besteht darin, bedingte Ausdrücke auszuwerten. Hier nützt es nichts.

Da umountauf seiner Standardausgabe nichts ausgegeben wird (die Fehler gehen zu stderr), wird `sudo umount mount`auf nichts erweitert.

So ist es wie:

while [ ]
do
  sleep 0.1
done

Der [Befehl, wenn kein Argument übergeben neben [und ]kehrt falsch (ein Nicht-Null - Exit - Status), so dass Sie nicht die Schleife ein.

Selbst wenn umountdie Fehler in stdout [ausgegeben worden wären, hätte die Verwendung des Befehls keinen Sinn ergeben, da die daraus resultierenden Wörter niemals einen gültigen Bedingungsausdruck ergeben hätten.

Hier möchten Sie:

until sudo umount mount
do
  sleep 0.1
done

Das heißt, Sie möchten den Exit-Status von sudo / umount und nicht eines [Befehls überprüfen .

Wenn Sie überprüfen wollten, ob umountein Fehler oder eine Warnung auf dem stderr ausgegeben wurde, [hätte das nützlich sein können. Dies -n "some-string"ist ein Bedingungsausdruck, der vom [Befehl zum Testen, ob "some-string"leer oder nicht, erkannt wird.

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

Das Vorhandensein von Fehler- oder Warnmeldungen ist jedoch im Allgemeinen eine schlechte Idee. Der umount Befehl sagt uns, ob er mit seinem Exit-Code erfolgreich ist oder nicht, das ist viel zuverlässiger. Es könnte erfolgreich sein und trotzdem eine Warnmeldung ausgeben. Es könnte fehlschlagen und keinen Fehler ausgeben (wie wenn es getötet wird).

Beachten Sie in diesem speziellen Fall, dass dies umountmöglicherweise fehlschlägt, da das Verzeichnis nicht bereitgestellt wird. In diesem Fall würden Sie eine Endlosschleife ausführen, sodass Sie einen anderen Ansatz wie den folgenden versuchen können:

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

Oder wenn "mount" mehrmals gemountet werden kann und Sie alle mounten möchten:

while mountpoint -q mount; do
  sudo umount mount || sleep 0.1
done
Stéphane Chazelas
quelle
Funktioniert, super!
Charliehorse55
1
1 den Unterschied zwischen der Verwendung zur Erläuterung [, [[oder nicht. Ich wünsche mir typische Manpages, GNU- und / oder TLDP-Beispiele zu Bash-Bedingungen, die solche Details behandeln
Renoirb,
5

wiederverwendbare Funktion und Timeout in 'n' Sekunden

_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
}

keine Notwendigkeit zu schlafen

Christopher Barry
quelle
1
[[...]]ist ksh/ bash/ zshspezifisch, die alle die $SECONDSspezielle Variable haben, also könnten Sie tun:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas
mount remount,roBeachten Sie, dass ein Befehl auf einem mips-Gerät anno 2009 mit einem Intenso Micro Line USB-Stick 23 oder sogar mehr als 30 Sekunden dauern kann .
Pro Backup