Скрипты Bash - цикл до возвращаемого значения 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, что означает, что он был успешно размонтирован?

charliehorse55
источник

Ответы:

59

Команда [для оценки условных выражений. Это бесполезно здесь.

Поскольку umountничего не выводит на стандартный вывод (ошибки идут в stderr), `sudo umount mount`ничего не расширяется.

Так что это как:

while [ ]
do
  sleep 0.1
done

Команда [, когда не передается ни одного аргумента, [и ]возвращает false (ненулевой статус выхода), поэтому вы не будете входить в цикл.

Даже если бы umountон выводил свои ошибки на стандартный вывод, использование [команды не имело бы смысла, потому что слова, полученные в результате этого вывода, никогда бы не составили действительное условное выражение.

Здесь вы хотите:

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 Для объяснения разницы между использованием [, [[или нет. Мне бы хотелось, чтобы типичные man-страницы, примеры 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 anno 2009 с USB-накопителем Intenso Micro Line может занять 23 или даже более 30 секунд .
Pro Backup