Script di Bash - loop fino a quando il valore restituito è 0


25

Devo smontare qualcosa nel mio script, ma a volte smonta prima che tutti i dati abbiano finito di essere copiati e non riesca a farlo. Ho cercato un modo per fare un "blocco" umount, ma non ho trovato nulla. Quindi, ho provato a scrivere uno script per eseguire il ciclo fino a quando non poteva essere smontato, ma non funziona.

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

Quando si eseguono le uscite:

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

Non dovrebbe essere in loop fino a quando il valore restituito sudo umount mountè 0, il che significa che è stato smontato correttamente?

Risposte:


59

Il [comando è valutare le espressioni condizionali. Non serve a niente qui.

Perché umountnon genera nulla sul suo output standard (gli errori vanno a stderr), non si `sudo umount mount`espande a nulla.

Quindi è come:

while [ ]
do
  sleep 0.1
done

Il [comando, quando non passa alcun argomento accanto [e ]restituisce false (uno stato di uscita diverso da zero), quindi non entrerai nel ciclo.

Anche se umountavesse generato i suoi errori su stdout, l'uso del [comando non avrebbe avuto senso, perché le parole risultanti da quell'output non avrebbero mai costituito un'espressione condizionale valida.

Qui vuoi:

until sudo umount mount
do
  sleep 0.1
done

Cioè, si desidera controllare lo stato di uscita di sudo / umount, non di un [comando.

Se volessi verificare se umountemetteva qualche errore o avvertimento sul suo standard, è qui che [avrebbe potuto essere utile. È -n "some-string"un'espressione condizionale riconosciuta dal [comando per verificare se "some-string"è vuota o meno, quindi qualcosa di simile a:

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

Ma cercare la presenza di messaggi di errore o di avviso è generalmente una cattiva idea. Il umount comando ci dice se riesce o meno con il suo codice di uscita, è molto più affidabile. Potrebbe avere successo e comunque generare un messaggio di avviso. Potrebbe non riuscire e non generare un errore (come quando viene ucciso).

In questo caso particolare, tieni presente che umountpotrebbe non riuscire perché la directory non è montata e in quel caso eseguiresti un ciclo per sempre, quindi potresti provare un altro approccio come:

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

O se "mount" può essere montato più volte e si desidera smontarli tutti:

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

Funziona a meraviglia!
charliehorse55,

1
+1 per spiegare la differenza tra l'utilizzo [, [[oppure no. Vorrei che man page tipiche, esempi GNU e / o TLDP sui condizionali bash coprissero tali dettagli
renoirb,

5

funzione riutilizzabile e scadrà tra 'n' secondi

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

non c'è bisogno di dormire


1
[[...]]è ksh/ bash/ zshspecific, ognuno dei quali ha la $SECONDSvariabile speciale, quindi potresti fare:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas

Tieni presente che il completamento di un mount remount,rocomando su un dispositivo mips anno 2009 con una chiavetta USB Intenso Micro Line può richiedere 23 o anche più di 30 secondi .
Pro Backup
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.