Jaki jest najlepszy sposób sprawdzenia, czy wolumin jest zamontowany w skrypcie Bash?


103

Jaki jest najlepszy sposób sprawdzenia, czy wolumin jest zamontowany w skrypcie Bash?

To, co naprawdę lubię, to metoda, której mogę użyć w następujący sposób:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi

Właśnie miałem napisać skrypt, aby to zrobić sam. Moją pierwszą myślą jest uzyskanie informacji z / etc / mtab. Ale nie przeglądałem jeszcze swoich bashowych książek, aby sprawdzić, czy istnieje bardziej bezpośredni sposób.
3dinfluence

@ 3dinfluence - tak wiem to z dawno temu, ale /etc/mtab, /proc/mountssą powiązane /proc/self/mounts. (przynajmniej na Fedorze 20)
Wilf

Podobne pytania dotyczą błędu serwera , przepełnienia stosu oraz wymiany stosu Unix i Linux .
Sasha

Odpowiedzi:


113

Unikaj używania, /etc/mtabponieważ może być niespójne.

Unikaj instalacji rurowej, mountponieważ nie musi to być tak skomplikowane.

Po prostu:

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

(Przestrzeń po /mnt/foojest, aby uniknąć dopasowania np /mnt/foo-bar.)


7
Nie wspominając, że wezwanie do montowania może się zawiesić, jeśli punkt montowania jest klinowany.
Chad Huneycutt,

8
Dobry dla Linuksa, nie dla Freebsd ani Solaris.
Chris

4
To prawda, Chris. Chociaż pytanie zostało oznaczone linuksem.
Dan Carley,

3
Sądzę, że jest to filozoficzne pytanie - czy powinniśmy spróbować uczynić rzeczy przenośnymi, jeśli to możliwe, czy powinniśmy po prostu założyć, że wszystkie systemy Windows / Linux działają na całym świecie i działać odpowiednio?
Chris

18
Właściwie powinieneś przetestować na „/ mnt / foo”, tj. ze spacją lub możesz uzyskać fałszywie dodatni, jeśli podłączyłeś wolumin o nazwie np. „fooks”. Właśnie dostałem ten problem z dwoma punktami montowania, „lmde” i „lmde-home”.
marlar

58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

lub

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"

4
Tylko dla informacji: mountpointpochodzi z pakietu „initscripts” w Ubuntu / Debian.
blueyed

1
Nie działało dla mnie - :-(
Wilf

To jest wezwanie, na którym opiera się mój włóczęga.
zjazd

Problem mountpointpolega na tym, że w rzeczywistości sprawdza, czy punkt montowania jest zamontowany, ale nie czy urządzenie jest zamontowane. Jeśli urządzenie zostanie przekazane z -xopcją, poda numer główny / podrzędny, ale nie, jeśli zostanie zamontowane.
vegatripy

@blueyed W Debian Buster jest dostarczany przez pakietutil-linux
elboulangero

18

findmnt -rno SOURCE,TARGET "$1"pozwala uniknąć wszystkich problemów zawartych w innych odpowiedziach. Czyści to dobrze za pomocą jednego polecenia.


Inne podejścia mają te wady:

  • grep -qi grep -ssą dodatkowym niepotrzebnym krokiem i nie są obsługiwane wszędzie.
  • /proc/\* nie jest obsługiwany wszędzie.
  • mountinfo jest oparty na / proc / ..
  • cut -f3 -d' ' miesza spacje w nazwach ścieżek
  • Biała przestrzeń analizowania wierzchowca jest problematyczna. Strona podręcznika mówi teraz:

.. tryb wyświetlania jest utrzymywany tylko dla kompatybilności wstecznej.

Aby uzyskać bardziej niezawodne i konfigurowalne dane wyjściowe, użyj findmnt (8), szczególnie w skryptach.


Funkcje 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

Przykłady użycia:

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
W przypadku Linuksa jest to naprawdę najlepsze podejście. Widziałem findmnt(8)polecenie, ale tak naprawdę nigdy się nim nie bawiłem. Szczerze mówiąc, gdybym miał zaktualizować niektóre moje skrypty, które robią tego typu rzeczy (lub tworzyć nowe) na Linux-ie (lub tam, gdzie dostępna jest komenda), to właśnie bym to zrobił.
Pryftan

1
Zauważ, że dla enfs, findmntmusi być dostarczony z parametrem --source encfs, w przeciwnym razie zawsze będzie rozważał katalog do zamontowania, ponieważ wraca do montowania nadrzędnego.
Burkart

Jest to również lepsze niż greprozwiązanie, ponieważ jeśli ścieżka podłączenia jest dziwne, można uzyskać fałszywych alarmów: np gdybym zamontować /dev/mmcblk0p1na ~/mnt/dev/sda1mogłem błędnie rzeczą, która /dev/sda1jest zamontowana za pomocą polecenia mount | grep '/dev/sda1'. Nie mogę uzyskać fałszywie pozytywnego wyniku findmnt. Dobra odpowiedź!
Cody Piersall

7

Taki skrypt nigdy nie będzie przenośny. Brudnym sekretem w Uniksie jest to, że tylko jądro wie, gdzie są systemy plików, a poza takimi rzeczami jak / proc (nieprzenośny) nigdy nie da ci prostej odpowiedzi.

Zazwyczaj używam df, aby dowiedzieć się, jaki jest punkt montowania podkatalogu i w jakim systemie plików on jest.

Na przykład (wymaga powłoki posix, takiej jak 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

Trochę mówi ci przydatne informacje.


1
Pytanie jest oznaczone linuksem, więc może nie musi być przenośne
Rory,

6

Oto, czego używam w jednym z moich zadań CRON do tworzenia kopii zapasowych rsync. sprawdza, czy / backup jest zamontowany i próbuje go zamontować, jeśli nie jest (może się nie powieść, ponieważ dysk znajduje się we wnęce typu hot-swap i może nawet nie być obecny w systemie)

UWAGA: poniższe działa tylko w systemie Linux, ponieważ greps / proc / mounts - w bardziej przenośnej wersji można uruchomić polecenie „mount | grep / backup ”, jak w odpowiedzi Matthew ..

  Jeśli ! grep -q / backup / proc / mounts; następnie
    Jeśli ! zamontować / wykonać kopię zapasową; następnie
      echo „nie powiodło się”
      wyjście 1
    fi
  fi
  echo „suceed”.
  # rób rzeczy tutaj

2
Uznany za dobrą alternatywę sprawdzania rozsądku.
Dan Carley,

Prawdopodobnie ta metoda napotyka te same problemy, co odpowiedź Matthew Blocha.
mwfearnley,

tak, z wyjątkiem kwestii spacji w nazwie pliku wspomnianej w „Eliptical view” (to grepuje całą linię, a nie tylko wyodrębnione pole). Kwestia podciągów nie jest wielką rzeczą, chyba że w jakiś sposób zapomnisz, że przytaczanie argumentów jest możliwe. np . grep -q ' /backup ' /proc/mountslub mount | grep -q ' /backup '. Lub przekieruj do / dev / null, jeśli twój grep nie obsługuje -q(który jest obecnie w specyfikacji POSIX dla grep).
cas

2

Ponieważ aby zamontować, musisz mieć tam katalog, który się zamontuje, moją strategią było zawsze tworzenie fałszywego pliku z dziwną nazwą pliku, który nigdy nie byłby używany, i po prostu sprawdzanie jego istnienia. Jeśli plik tam był, to nic nie zostało zamontowane w tym miejscu ...

Nie sądzę, że to działa do montowania dysków sieciowych lub podobnych rzeczy. Użyłem go do dysków flash.


2

Co powiesz na porównanie numerów urządzeń? Chciałem tylko wymyślić najbardziej ezoteryczny sposób ...

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

Z moją logiką jest wada ...

Jako funkcja:

#!/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

Komunikaty o błędach echa są prawdopodobnie zbędne, ponieważ stat wyświetli również błąd.


Właściwie prawdopodobnie musiałbym najpierw sprawdzić status wyjścia statystyki dla każdego wywołania, aby upewnić się, że plik tam jest ... nie tak nowatorski, jak myślałem :-(
Kyle Brandt

1

Żaden z nich nie spełnia przypadku użycia, w którym dany katalog jest podkatalogiem w innym punkcie podłączenia. Na przykład możesz mieć / thing, który jest podłączeniem NFS do hosta: / real_thing. Użycie grep w tym celu na / proc / mounts / etc / mtab lub 'mount' nie będzie działać, ponieważ będziesz szukał punktu montowania, który nie istnieje. Na przykład / rzecz / rzecz nie jest punktem montowania, ale / rzecz jest zamontowane na hoście: / real_thing. Najlepsza odpowiedź tutaj głosowana NIE jest „najlepszym sposobem na ustalenie, czy katalog / wolumen jest zamontowany”. Głosowałbym za użyciem „df -P” (tryb standardów -P POSIX) jako czystszej strategii:

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

Wynikiem uruchomienia będzie:

Mounted via: host:/real_thing

Jeśli chcesz wiedzieć, jaki jest prawdziwy punkt montowania, nie ma problemu:

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

Dane wyjściowe tego polecenia będą następujące:

Mounted on: /thing

Jest to bardzo przydatne, jeśli próbujesz utworzyć pewnego rodzaju chroot, który odzwierciedla punkty montowania poza chroot, wewnątrz chroot, za pośrednictwem dowolnego katalogu lub listy plików.


1

Przepraszam, że o tym wspomniałem, ale myślę, że jest to całkiem przydatne:

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

Otrzymuje drugą kolumnę / proc / mounts (druga kolumna = punkty montowania).

Następnie grepuje dane wyjściowe. Uwaga ^ i $, zapobiega to dopasowaniu / backup do / mnt / backup lub / backup-old itp.


0

może grep / etc / mtab dla twojego punktu montowania?


1
mtab może być nieaktualny lub po prostu nie być aktualizowany przez mount, na przykład gdy używasz mount -n, ponieważ / jest tylko do odczytu.
Chris

Zgadzam się, ale wydawało się, że to pierwsze miejsce, w którym można zacząć szukać.
Ophidian


0

Chociaż jest to pytanie dotyczące systemu Linux, dlaczego nie uczynić go przenośnym, gdy można go łatwo wykonać?

Strona podręcznika grepmówi:

Przenośne skrypty powłoki powinny unikać zarówno -q, jak i -s i /dev/nullzamiast tego powinny przekierowywać wyjście standardowe i wyjście błędu .

Proponuję więc następujące rozwiązanie:

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

3
Wiele systemów UNIX nie udostępnia systemu plików / proc
Dmitri Chubarov,

@DmitriChubarov Rzeczywiście. Co sprawia, że ​​koncepcja przenośności jest ironiczna, prawda? A może jest to nowsza aktualizacja ale -qi -ssą określone przez POSIX, więc nie powinno być żadnego problemu z tym i tak przenośność (obecnie jeśli nie przed - I już nie śledził, co zmienia się, gdy).
Pryftan

0

Czy to musi być bardziej skomplikowane?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"

1
grep -q /mnt/foobędą również pasować do punktów montowania /mnt/foodi /not/mnt/foo... Co powiesz na grep -qx /mnt/foo?
rakslice,

@rakslice: to nie zadziała. -xdopasowuje grep tylko wtedy, gdy pasuje cała linia.
mivk 17.12

1
cut -f 3 -d ' 'potknie się, gdy ścieżka montowania ma spację w nazwie pliku.
Eliptyczny widok

0

Zależy od tego, co wiesz o woluminie, którego szukasz.

W konkretnym przypadku, który ostatnio badałem, w którym martwiłem się, czy konkretny dysk flash został zamontowany, najłatwiej działa sprawdzenie istnienia / dev / disks / by-label /. Jeśli urządzenie jest podłączone, skrypty udev upewniają się, że link istnieje (i że jest usuwany, gdy urządzenie jest odłączone).

(To NIE jest bardzo przenośna odpowiedź; działa jednak na wiele współczesnych dystrybucji Linuksa, a pytanie zostało oznaczone dla Linuksa i jest to zupełnie inne podejście niż wszystko, co do tej pory wspomniano, więc rozszerza możliwości.)


0

Utwórz plik pod swoim punktem montowania, check_mounta następnie po prostu przetestuj, czy istnieje?

if [[ -f /something/check_mount ]]; then
   echo "Mounted
   RC=$?
else
   Echo "Not mounted"
   RC=0
fi
exit $RC

-1

Musiałem to zrobić w Chef dla idempotencji, ponieważ kiedy szef kuchni-klient działał, bieg nie udawał się z powodu już zamontowanego woluminu. W chwili, gdy to piszę, mountzasób szefa kuchni ma jakiś błąd, który nie działałby z atrybutami tak, jak potrzebowałem, więc executezamiast tego zamontowałem wolumin za pomocą tego zasobu. Oto jak to zrobiłem:

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

W przypadku jakichkolwiek nieporozumień w moim pliku atrybutów mam:

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

if not node['docker-server']['mountpoint'] == "none"Jest częścią caserachunku gdzie jeśli punkt instalacji na serwerze nie jest określony, punkt montowania do domyślnych none.


... i co to ma wspólnego z pierwotnym pytaniem?!?
Massimo,

Stosunek komentarza mojego przepisu szefa kuchni do pierwotnego pytania polega na tym, że ludzie coraz bardziej dążą do automatyzacji. Dlatego jeśli ktoś tu przyjdzie i zastanawia się, jak sprawić, by działał w przepisie szefa kuchni, będzie miał odpowiedź. W życiu są dwie opcje: 1) Zrób minimum i spraw, aby niektórzy ludzie byli szczęśliwi, i 2) Idź o krok dalej. Dlatego zamiast oznaczać mój post w dół, zaakceptuj go takim, jakim jest: dodatkowymi informacjami, które potwierdzają przyjętą odpowiedź.
KLaw

Pytanie dotyczyło skryptów bashowych, twoja odpowiedź dotyczy skryptów szefów kuchni. Chociaż może być przydatny dla kogoś, nadal nie ma znaczenia dla pytania.
Massimo,

@KLaw „Dlatego zamiast oznaczać mój post w dół, zaakceptuj go takim, jakim jest: dodatkowe informacje, które potwierdzają przyjętą odpowiedź”. Zgadzam się i zazwyczaj nie głosuję za głosem (a ja też tu nie mam), ale jeśli masz problem z tego typu rzeczami, może powinieneś dodać to jako uzupełnienie innych punktów? Może zapisać inne komentarze. Ale jeśli chodzi o automatyzację, właśnie na to pozwalają skrypty bash, więc nie rozumiem, o co ci chodzi. Oczywiście programista we mnie uważa, że ​​powyższy skrypt jest ohydny, ale jest to problem językowy bardziej niż cokolwiek innego ...
Pryftan
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.