Bash scripting - цикл, поки значення повернення не дорівнює 0


25

Мені потрібно щось вимкнути в моєму сценарії, але іноді він відключається до того, як всі дані закінчено копіюватись і спричиняє збій цього тексту. Я шукав спосіб зробити "блокуючий" мантаж, але нічого не знайшов. Отже, я спробував написати сценарій для циклу, поки його не можна було відключити, але це не працює.

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

Під час запуску виходів:

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 mountдорівнює 0, це означає, що воно було успішно змінено?

Відповіді:


59

[Команда для оцінки умовних виразів. Тут нічого не потрібно.

Оскільки umountна стандартному виході нічого не виводиться (помилки йдуть до stderr), `sudo umount mount`розширюється до нічого.

Так це:

while [ ]
do
  sleep 0.1
done

[Команда, коли не передається ніяких аргументів поруч [і ]повертає брехня (стан виходу не нуль), так що ви не ввійдете в петлю.

Навіть якби umountвиводив свої помилки на stdout, використання [команди не мало б сенсу, оскільки слова, отримані в результаті цього виводу, ніколи не склали б дійсного умовного вираження.

Тут ви хочете:

until sudo umount mount
do
  sleep 0.1
done

Тобто ви хочете перевірити статус виходу sudo / umount, а не [команди.

Якщо ви хочете перевірити, чи umountвиводить якусь помилку чи попередження на її stderr, саме тут [міг би бути корисним. Це -n "some-string"умовний вираз, розпізнаваний [командою для перевірки, чи "some-string"порожній він чи ні, тож щось подібне:

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

Але шукати наявність помилок або попереджувальних повідомлень, як правило, погана ідея. umount Команда говорить нам про те , чи не вдається це з кодом виходу, що набагато надійніше. Це могло б досягти успіху та все-таки вивести якесь попереджувальне повідомлення. Він може вийти з ладу і не вивести помилку (наприклад, коли він вбитий).

У цьому конкретному випадку зауважте, що це umountможе бути невдалим, оскільки каталог не змонтований, і в цьому випадку ви назавжди цикла, тож ви можете спробувати інший підхід, наприклад:

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

Або якщо "mount" може бути встановлений кілька разів, і ви хочете їх відключити:

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

Працює, дивовижно!
charliehorse55

1
+1 Для пояснення різниці між використанням [, [[чи ні. Я хочу, щоб типові сторінки чоловіків, GNU та / або TLDP прикладами про баш-умовні умови висвітлювали таку деталь
перегляньте

5

функція багаторазового використання, і час очікується протягом 'n' секунд

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

не потрібно спати


1
[[...]]є ksh/ bash/ zshконкретні, всі з яких мають $SECONDSспеціальну змінну, так що ви можете зробити:SECONDS=0; until umount... || ((SECONDS > $1)); do..
Stéphane Chazelas

Майте на увазі, що mount remount,roкоманда на пристрої mips, який відбудеться в 2009 році, за допомогою USB-накопичувача Intenso Micro Line, може виконати 23 або навіть 30+ секунд .
Pro Backup
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.