Как лучше всего проверить, смонтирован ли том в скрипте Bash?

103

Как лучше всего проверить, смонтирован ли том в скрипте Bash?

Что мне действительно нравится, так это метод, который я могу использовать так:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi
Марк Бик
источник
Я как раз собирался написать сценарий, чтобы сделать это сам. Моя первая мысль - получить информацию из / etc / mtab Но я еще не пролистал свои bash книги, чтобы посмотреть, есть ли более прямой путь.
3dinfluence
@ 3dinfluence - да, я знаю это давным-давно, но /etc/mtab, /proc/mountsсвязаны с /proc/self/mounts. (по крайней мере, на Fedora 20 это так)
Уилф
Подобные вопросы касаются неисправностей сервера , переполнения стека и Unix & Linux Stack Exchange .
Саша

Ответы:

113

Избегайте использования, /etc/mtabпотому что это может быть противоречивым.

Избегайте труб, mountпотому что это не должно быть так сложно.

Просто:

if grep -qs '/mnt/foo ' /proc/mounts; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

(Пробел после /mnt/fooдолжен избегать совпадения, например /mnt/foo-bar.)

Дэн Карли
источник
7
Не говоря уже о том, что вызов mount может зависнуть, если точка монтирования заклинена.
Чад Хьюникутт
8
Хорошо для Linux, а не для FreeBSD или Solaris.
Крис
4
Это правда, Крис. Хотя вопрос был помечен linux.
Дэн Карли
3
Я думаю, это философский вопрос - должны ли мы попытаться сделать вещи переносимыми, если это возможно, или мы должны просто предположить, что все в мире работают под управлением windows / linux и действовать соответственно?
Крис
18
На самом деле, вы должны проверить на «/ mnt / foo», т.е. с пробелом или вы можете получить ложное срабатывание, если вы смонтировали том с именем, например. 'fooks'. Я только что получил эту проблему с двумя точками монтирования, lmde и lmde-home.
marlar
58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

или же

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"
Zaptac
источник
4
Просто для информации: mountpointпроисходит из пакета "initscripts" в Ubuntu / Debian.
синеватый
1
У меня не сработало - :-(
Уилф
Это зов, на котором висит мой Бродяга.
dhill
Проблема в mountpointтом, что он фактически проверяет, смонтирована ли точка монтирования, но не монтируется ли устройство. Если устройство передается с -xопцией, оно сообщает вам основной / вспомогательный номер устройства, но не указывает, подключено ли оно.
вегатрипы
@blueyed В Debian Buster он предоставляется пакетомutil-linux
elboulangero
18

findmnt -rno SOURCE,TARGET "$1"избегает всех проблем в других ответах. Это чисто делает работу с одной командой.


Другие подходы имеют следующие недостатки:

  • grep -qи grep -sявляются дополнительным ненужным шагом и не поддерживаются везде.
  • /proc/\* не поддерживается везде
  • mountinfo основан на / proc / ..
  • cut -f3 -d' ' портит пробелы в именах путей
  • Разбирая пробел маунта проблематично. Это страница руководства теперь говорит:

.. Режим листинга поддерживается только для обратной совместимости.

Для более надежного и настраиваемого вывода используйте findmnt (8), особенно в ваших скриптах.


Bash функции:

#These functions return exit codes: 0 = found, 1 = not found

isMounted    () { findmnt -rno SOURCE,TARGET "$1" >/dev/null;} #path or device
isDevMounted () { findmnt -rno SOURCE        "$1" >/dev/null;} #device only
isPathMounted() { findmnt -rno        TARGET "$1" >/dev/null;} #path   only

#where: -r = --raw, -n = --noheadings, -o = --output

Примеры использования:

if isPathMounted "/mnt/foo bar";      #Spaces in path names are ok.
   then echo "path is mounted"
   else echo "path is not mounted"
fi

if isDevMounted "/dev/sdb4"; 
   then echo "device is mounted"
   else echo "device is not mounted"
fi

#Universal:
if isMounted "/mnt/foo bar"; 
   then echo "device is mounted"
   else echo "device is not mounted"
fi

if isMounted "/dev/sdb4";
   then echo "device is mounted"
   else echo "device is not mounted"
fi
Эллиптический вид
источник
1
В любом случае для Linux это действительно лучший подход. Я видел findmnt(8)команду, но никогда не играл с ней. Честно говоря, если бы я обновил некоторые из моих сценариев, которые делают подобные вещи (или делают новые) на Linux-боксе (или там, где команда доступна), это то, что я сделал бы.
Прифтан
1
Обратите внимание, что для encfs findmntнеобходимо указывать этот параметр --source encfs, в противном случае он всегда будет считать каталог подключенным, поскольку он возвращается к родительскому подключению.
Burkart
Это также лучше , чем grepрешение , потому что , если путь монтирования странно, вы можете получить ложные срабатывания: например , если я устанавливаю /dev/mmcblk0p1на ~/mnt/dev/sda1, я мог бы неправильно вещь , которая /dev/sda1крепится с помощью команды mount | grep '/dev/sda1'. Я не могу получить ложное срабатывание, используя findmnt. Хороший ответ!
Коди Пирсолл
7

Такой сценарий никогда не будет переносимым. Грязный секрет в unix состоит в том, что только ядро ​​знает, где находятся файловые системы, и, за исключением таких вещей, как / proc (не переносимый), он никогда не даст вам прямого ответа.

Обычно я использую df, чтобы узнать, что такое точка монтирования подкаталога и в какой файловой системе он находится.

Например (требуется оболочка posix, например, ash / AT & T ksh / bash / etc)

case $(df  $mount)
in
  $(df  /)) echo $mount is not mounted ;;
  *) echo $mount has a non-root filesystem mounted on it ;;
esac

Кинда рассказывает вам полезную информацию.

Крис
источник
1
Вопрос помечен как linux, так что, возможно, он не должен быть переносимым
Рори
6

Вот что я использую в одном из моих заданий cron резервного копирования rsync. он проверяет, смонтирован ли / backup, и пытается смонтировать его, если это не так (может произойти сбой, потому что диск находится в отсеке горячей замены и может даже не присутствовать в системе)

ПРИМЕЧАНИЕ: следующее работает только на linux, потому что это greps / proc / mounts - более переносимая версия запускает 'mount | grep / backup ', как в ответе Мэтью ..

  если ! grep -q / backup / proc / mounts; тогда
    если ! монтирование / резервное копирование; тогда
      эхо "не удалось"
      выход 1
    фи
  фи
  эхо "успешно"
  # делать вещи здесь
саз
источник
2
Признан хорошей альтернативой проверки здравомыслия.
Дэн Карли
Предположительно, этот метод сталкивается с теми же проблемами, что и ответ Мэтью Блоха.
mwfearnley
да, за исключением проблемы пробела в имени файла, упомянутой "Eliptical view" (это затрагивает всю строку, а не только извлеченное поле). Проблема с подстрокой не имеет большого значения, если вы не забудете, что аргументы в кавычках - это то, что вы можете сделать. например grep -q ' /backup ' /proc/mountsили mount | grep -q ' /backup '. Или перенаправлять / DEV / нуль , если ваш Grep не поддерживает -q(который находится в POSIX спецификации для Grep в эти дни).
саз
2

Так как для монтирования вам в любом случае необходимо иметь каталог, который монтируется, моя стратегия всегда заключалась в том, чтобы создать поддельный файл со странным именем файла, которое никогда не будет использоваться, и просто проверить его существование. Если файл был там, то на этом месте ничего не было смонтировано ...

Я не думаю, что это работает для подключения сетевых дисков или подобных вещей. Я использовал его для флешек.

Брайан Постов
источник
2

Как насчет сравнения номеров устройств? Я просто пытался придумать самый эзотерический способ ..

#!/bin/bash
if [[ $(stat -c "%d" /mnt) -ne $(stat -c "%d" /mnt/foo) ]]; then
    echo "Somethin mounted there I reckon"
fi

В моей логике есть недостаток ...

Как функция:

#!/usr/bin/bash
function somethingMounted {
        mountpoint="$1"
        if ! device1=$(stat -c "%d" $mountpoint); then
                echo "Error on stat of mount point, maybe file doesn't exist?" 1>&2
                return 1
        fi
        if ! device2=$(stat -c "%d" $mountpoint/..); then
                echo "Error on stat one level up from mount point, maybe file doesn't exist?" 1>&2
                return 1
        fi

        if [[ $device1 -ne $device2 ]]; then
                #echo "Somethin mounted there I reckon"
                return 0
        else
                #echo "Nothin mounted it seems"
                return 1
        fi
}

if somethingMounted /tmp; then
        echo "Yup"
fi

Сообщения об эхо-ошибках, вероятно, являются избыточными, потому что stat также будет отображать ошибку.

Кайл Брандт
источник
На самом деле, вероятно, придется проверять состояние выхода stat в первую очередь для каждого вызова, чтобы убедиться, что файл там есть ... не такой новый, как я думал :-(
Кайл Брандт
1

Ни один из них не удовлетворяет случаю использования, где данный каталог является подкаталогом в другой точке монтирования. Например, у вас может быть / вещь, которая является монтированием NFS к хосту: / real_thing. Использование grep для этой цели в / proc / mounts / etc / mtab или 'mount' не будет работать, потому что вы будете искать точку монтирования, которая не существует. Например, / thing / thingy не является точкой монтирования, но / thing монтируется на хосте: / real_thing. Наилучший ответ, за который проголосовали здесь, на самом деле НЕ "лучший способ определить, смонтирован ли каталог / volumne". Я бы проголосовал за использование «df -P» (режим стандартов -P POSIX) в качестве более чистой стратегии:

dev=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print $1 ; exit } END { exit e }'` && {
    echo "Mounted via: $dev"
} || {
    echo "Not mounted"
}

Результат выполнения этого будет:

Mounted via: host:/real_thing

Если вы хотите знать, какова реальная точка монтирования, не проблема:

mp=`df -P /thing/thingy | awk 'BEGIN {e=1} $NF ~ /^\/.+/ { e=0 ; print $NF ; exit } END { exit e }'` && {
    echo "Mounted on: $mp"
} || {
    echo "Not mounted"
}

Результатом этой команды будет:

Mounted on: /thing

Все это очень полезно, если вы пытаетесь создать какой-либо chroot, который отражает точки монтирования вне chroot, внутри chroot, через какой-либо произвольный каталог или список файлов.

Craig
источник
1

Извините, что поднял этот вопрос, но я думаю, что это довольно полезно:

if awk '{print $2}' /proc/mounts | grep -qs "^/backup$"; then
    echo "It's mounted."
else
    echo "It's not mounted."
fi

Это получает 2-й столбец / proc / mounts (2-й столбец = точки монтирования).

Затем он получает вывод. Обратите внимание на ^ и $, это предотвращает совпадение / backup / mnt / backup или / backup-old и т. Д.

Дэвид
источник
0

grep / etc / mtab для вашей точки монтирования может быть?

змееподобный
источник
1
mtab может устареть или просто не обновляться при монтировании, например, когда вы используете mount -n, потому что / только для чтения.
Крис
Я согласен, но это было первое место, чтобы начать искать.
Офидиан
0

Этот?:

volume="/media/storage"
if mount|grep $volume; then
echo "mounted"
else
echo "not mounted"
if

От: форум Ubuntu

битпоток
источник
0

Хотя это вопрос Linux, почему бы не сделать его переносимым, когда это легко сделать?

Страница руководства grepговорит:

Портативные сценарии оболочки должны избегать как -q, так и -s и /dev/nullвместо этого перенаправлять стандартный вывод и вывод ошибок .

Поэтому я предлагаю следующее решение:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi
FEX
источник
3
Многие системы UNIX не предоставляют файловую систему / proc
Дмитрий Чубаров
@DmitriChubarov Действительно. Что делает концепцию переносимости ироничной, не так ли? А может быть , это более недавнее обновление , но -qи -sуказаны POSIX , так что не должно быть никаких портативность проблема с ним в любом случае ( в настоящее время , если не раньше - я не отслеживал , какие изменения происходят , когда).
Прифтан
0

Должно ли это быть более сложным, чем это?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"
Мэтью Блох
источник
1
grep -q /mnt/fooтакже будет соответствовать точкам монтирования /mnt/foodи /not/mnt/foo... Как насчет grep -qx /mnt/foo?
Ракслице
@rakslice: это не сработает. -xделает grep match только если вся строка совпадает.
MIVK
1
cut -f 3 -d ' 'спотыкается, когда путь монтирования имеет пробел в имени файла.
эллиптический вид
0

Зависит от того, что вы знаете о том, что вы проверяете.

В конкретном случае, который я недавно исследовал, когда меня интересовало, был ли установлен конкретный флеш-накопитель, что проще всего проверить на наличие / dev / disc / by-label /. Если устройство подключено, сценарии udev удостоверяются, что ссылка существует (и что она удаляется при отключении устройства).

(Это не очень переносимый ответ; он работает во многих современных дистрибутивах Linux, однако, вопрос был помечен для Linux, и это совершенно иной подход, чем когда-либо упоминавшийся, поэтому он расширяет возможности.)

Дэвид Дайер-Беннет
источник
0

Создать файл под точкой монтирования, check_mountа затем просто проверить, существует ли он?

if [[ -f /something/check_mount ]]; then
   echo "Mounted
   RC=$?
else
   Echo "Not mounted"
   RC=0
fi
exit $RC
Wiljami
источник
-1

Мне пришлось сделать это в Chef для идемпотентности, так как при запуске chef-client запуск завершился неудачей из-за того, что том уже смонтирован. В то время, когда я пишу это, у mountресурса Chef есть какая-то ошибка, которая не работает с атрибутами так, как мне нужно, поэтому я смонтировал том с помощью executeресурса. Вот как я это сделал:

if not node['docker-server']['mountpoint'] == "none"
  execute "set up mount" do
    user "root"
    command "mount -t ext4 #{node['docker-server']['mountpoint']} #{node['docker-server']['data-dir']}"
    not_if "grep -qs #{node['docker-server']['data-dir']} /proc/mounts"
  end
end

В случае путаницы в моем файле атрибутов у меня есть следующее:

default['docker-server']['mountpoint'] = "/dev/vdc"
default['docker-server']['data-dir'] = "/data"

Это if not node['docker-server']['mountpoint'] == "none"часть caseинструкции, в которой, если точка монтирования на сервере не указана, по умолчанию используется точка монтирования none.

Клоу
источник
... и какое это имеет отношение к первоначальному вопросу?!?
Массимо
Отношение моего рецепта шеф-повара к первоначальному вопросу заключается в том, что люди все больше двигаются в сторону автоматизации. Поэтому, если кто-то придет сюда с вопросом, как сделать это по рецепту шеф-повара, у него будет ответ. В жизни есть два варианта: 1) сделать минимум и порадовать некоторых людей, и 2) пройти лишнюю милю. Поэтому вместо того, чтобы пометить мой пост, примите его таким, какой он есть: дополнительная информация, подтверждающая принятый ответ.
KLaw
Вопрос был о скриптах bash, ваш ответ о скриптах Chef. Хотя это может быть полезно для кого-то, оно по-прежнему не имеет никакого отношения к вопросу.
Массимо
@KLaw «Поэтому, вместо того, чтобы пометить мой пост, примите его таким, какой он есть: дополнительная информация, подтверждающая принятый ответ». Я согласен, и я не из тех, кто обычно голосует против (и у меня его здесь тоже нет), но если у вас есть проблемы с такими вещами, возможно, вам стоит добавить их в дополнение к другим вашим пунктам? Можно сохранить другие комментарии. Но что касается автоматизации, это именно то, что позволяют bash-скрипты, поэтому я не вижу вашей точки зрения. Конечно, программист во мне думает, что приведенный выше сценарий отвратителен, но это проблема языка больше всего на свете ...
Pryftan