Как лучше всего проверить, смонтирован ли том в скрипте 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"

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, через какой-либо произвольный каталог или список файлов.


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

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

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

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

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

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi

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

-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
Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.