Skrypty Bash - zapętlaj, aż wartość zwracana to 0


25

Muszę umountować coś w moim skrypcie, ale czasami to odmontowuje, zanim wszystkie dane skończą się kopiować i spowoduje awarię umount. Szukałem sposobu na zablokowanie umounta, ale niczego nie znalazłem. Próbowałem więc napisać skrypt, który zapętli się, dopóki nie będzie można go odmontować, ale nie działa.

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

Po uruchomieniu wyjścia:

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

Czy nie powinien zapętlać się, dopóki zwracana wartość sudo umount mountnie wyniesie 0, co oznacza, że ​​został pomyślnie zamontowany

Odpowiedzi:


59

[Komenda jest ocena wyrażeń warunkowych. Tu nie ma sensu.

Ponieważ umountnie wypisuje niczego na standardowym wyjściu (błędy idą do stderr), `sudo umount mount`rozwija się do zera.

To jest jak:

while [ ]
do
  sleep 0.1
done

[Poleceń, gdy nie przeszedł obok żadnego argumentu [i ]zwraca fałsz (exit status non-zero), więc nie wejdzie w pętlę.

Nawet gdyby umountwypisał swoje błędy na standardowe wyjście, użycie [polecenia nie miałoby sensu, ponieważ słowa wynikające z tego wyjścia nigdy nie tworzyłyby poprawnego wyrażenia warunkowego.

Tutaj chcesz:

until sudo umount mount
do
  sleep 0.1
done

Oznacza to, że chcesz sprawdzić status wyjścia sudo / umount, a nie [polecenia.

Jeśli chcesz sprawdzić, czy umountwypisuje jakiś błąd lub ostrzeżenie na swoim stderr, to [może być przydatne. Jest -n "some-string"to wyrażenie warunkowe rozpoznawane przez [polecenie sprawdzające, czy "some-string"jest puste, czy nie, więc coś w stylu:

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

Ale szukanie komunikatów o błędach lub ostrzeżeniach jest ogólnie złym pomysłem. umount Komenda mówi nam, czy nie powiedzie się z jego kod wyjścia, który jest dużo bardziej niezawodny. Może się udać i nadal wyświetla komunikat ostrzegawczy. Może się nie powieść i nie wygenerować błędu (np. Kiedy zostanie zabity).

W tym konkretnym przypadku zwróć uwagę, że umountmoże się to nie powieść, ponieważ katalog nie jest podłączony, w takim przypadku zapętlasz się na zawsze, abyś mógł wypróbować inne podejście, takie jak:

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

Lub jeśli „mount” może być zamontowany kilka razy i chcesz je wszystkie odmontować:

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

Działa świetnie!
charliehorse55

1
+1 dla wyjaśnienia różnicy między użyciem [, [[czy nie. Chciałbym, aby typowe strony podręcznika, przykłady GNU i / lub TLDP na temat warunkowych
bashów zawierały

5

funkcja wielokrotnego użytku i upłynie limit czasu za 'n' sekund

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

nie trzeba spać


1
[[...]]jest ksh/ bash/ zshspecific, z których wszystkie mają $SECONDSspecjalną zmienną, więc możesz zrobić:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas

Pamiętaj, że wykonanie mount remount,ropolecenia na urządzeniu mips anno 2009 z pamięcią USB Intenso Micro Line może potrwać 23, a nawet ponad 30 sekund .
Pro Backup
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.