Bash scripting - loop sampai nilai kembali adalah 0


25

Saya perlu umount sesuatu di skrip saya, tetapi kadang-kadang unmount sebelum semua data selesai disalin dan menyebabkan umount gagal. Saya mencari cara untuk melakukan "memblokir" umount, tetapi saya tidak menemukan apa pun. Jadi, saya mencoba menulis skrip untuk diulang sampai dapat di-unmount, tetapi tidak berhasil.

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

Saat menjalankan output:

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

sudo umount mountTidakkah seharusnya loop sampai nilai pengembalian adalah 0, yang berarti itu berhasil di-umount?

Jawaban:


59

The [perintah untuk mengevaluasi ekspresi kondisional. Tidak ada gunanya di sini.

Karena umounttidak menampilkan apa pun pada output standarnya (kesalahan mengarah ke stderr), `sudo umount mount`tidak akan berkembang.

Jadi seperti:

while [ ]
do
  sleep 0.1
done

The [perintah, bila tidak lulus argumen samping [dan ]kembali palsu (status exit non-nol), sehingga Anda tidak akan masuk loop.

Bahkan jika umountmemiliki output kesalahannya di stdout, menggunakan [perintah tidak akan masuk akal, karena kata-kata yang dihasilkan dari output itu tidak akan pernah membuat ekspresi kondisional yang valid.

Di sini Anda ingin:

until sudo umount mount
do
  sleep 0.1
done

Artinya, Anda ingin memeriksa status keluar dari sudo / umount, bukan dari [perintah.

Jika Anda ingin memeriksa apakah umountada kesalahan atau peringatan pada stderrnya, di situlah [bisa berguna. Ini -n "some-string"adalah ekspresi kondisional yang dikenali oleh [perintah untuk menguji apakah "some-string"kosong atau tidak, jadi sesuatu seperti:

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

Namun mencari keberadaan pesan kesalahan atau peringatan pada umumnya adalah ide yang buruk. The umount perintah memberitahu kita apakah atau tidak berhasil dengan kode keluar nya, itu jauh lebih dapat diandalkan. Itu bisa berhasil dan masih menampilkan beberapa pesan peringatan. Itu bisa gagal dan tidak menghasilkan kesalahan (seperti ketika itu terbunuh).

Dalam kasus khusus ini, perhatikan bahwa umountmungkin gagal karena direktori tidak di-mount, dan Anda akan mengulang selamanya dalam kasus itu, sehingga Anda bisa mencoba pendekatan lain seperti:

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

Atau jika "mount" mungkin dipasang beberapa kali dan Anda ingin meng-unmount semuanya:

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

Bekerja, luar biasa!
charliehorse55

1
+1 untuk menjelaskan perbedaan antara menggunakan [, [[atau tidak. Saya berharap halaman manual khas, contoh GNU dan / atau TLDP tentang persyaratan bash mencakup detail seperti itu
renoirb

5

fungsi dapat digunakan kembali, dan akan habis dalam 'n' detik

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

tidak perlu tidur


1
[[...]]adalah ksh/ bash/ zshspesifik, yang semuanya memiliki $SECONDSvariabel khusus, sehingga Anda dapat melakukan:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas

Perlu diingat bahwa mount remount,roperintah pada perangkat mips mengumumkan 2009 dengan stik USB Intenso Micro Line dapat memakan waktu 23 atau bahkan 30+ detik untuk menyelesaikannya.
Pro Backup
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.