Wie kann am besten überprüft werden, ob ein Volume in einem Bash-Skript eingebunden ist?

103

Wie kann am besten überprüft werden, ob ein Volume in einem Bash-Skript eingebunden ist?

Was ich wirklich gerne hätte, ist eine Methode, die ich so anwenden kann:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi
Mark Biek
quelle
Ich wollte gerade ein Skript schreiben, um dies selbst zu tun. Mein erster Gedanke ist, Informationen aus / etc / mtab zu holen. Aber ich habe meine Bash-Bücher noch nicht durchgesehen, um zu sehen, ob es einen direkteren Weg gibt.
3dinfluence
@ 3dinfluence - ja , ich weiß , das von vor langer Zeit, aber /etc/mtab, /proc/mountssind verbunden /proc/self/mounts. (zumindest auf Fedora 20 ist es)
Wilf
Ähnliche Fragen betreffen Serverfehler , Stapelüberlauf und Unix- und Linux-Stapelaustausch .
Sasha

Antworten:

113

Vermeiden Sie die Verwendung, /etc/mtabda dies inkonsistent sein kann.

Vermeiden Sie Rohrleitungen, mountda diese nicht so kompliziert sein müssen.

Einfach:

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

(Das Leerzeichen nach dem /mnt/fooist zu vermeiden /mnt/foo-bar.)

Dan Carley
quelle
7
Ganz zu schweigen davon, dass ein Aufruf zum Einhängen hängen bleiben kann, wenn der Einhängepunkt eingeklemmt ist.
Chad Huneycutt
8
Gut für Linux, nicht für Freebsd oder Solaris.
Chris
4
Das ist wahr, Chris. Obwohl die Frage Linux getaggt wurde.
Dan Carley
3
Ich denke, das ist eine philosophische Frage - sollten wir versuchen, Dinge tragbar zu machen, wenn es möglich ist, oder sollten wir einfach davon ausgehen, dass alle Windows / Linux-Betriebssysteme der Welt laufen und dementsprechend handeln?
chris
18
Eigentlich solltest du auf '/ mnt / foo' testen, also. mit einem Leerzeichen oder Sie erhalten möglicherweise ein falsches Positiv, wenn Sie ein Volume mit dem Namen z. "Fooks". Ich habe gerade dieses Problem mit zwei Einhängepunkten, 'lmde' und 'lmde-home'.
Marlar
58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

oder

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"
Zaptac
quelle
4
Nur zur Information: mountpointstammt aus dem "initscripts" -Paket in Ubuntu / Debian.
bläulich
1
Hat bei mir nicht funktioniert - :-(
Wilf
Dies ist der Ruf, an dem mein Vagrant hängt.
Dhill
Das Problem dabei mountpointist, dass überprüft wird, ob ein Bereitstellungspunkt bereitgestellt ist, nicht jedoch, ob ein Gerät bereitgestellt ist. Wenn ein Gerät mit der -xOption übergeben wird, wird die Haupt- / Nebengerätenummer angezeigt, nicht jedoch, wenn es aktiviert ist.
Vegatripy
@blueyed In Debian Buster wird es vom Paket bereitgestelltutil-linux
elboulangero,
18

findmnt -rno SOURCE,TARGET "$1"vermeidet alle Probleme in den anderen Antworten. Es erledigt die Arbeit sauber mit nur einem Befehl.


Andere Ansätze haben diese Nachteile:

  • grep -qund grep -ssind ein unnötiger zusätzlicher Schritt und werden nicht überall unterstützt.
  • /proc/\* wird nicht überall unterstützt.
  • mountinfo basiert auf / proc / ..
  • cut -f3 -d' ' Versaut Leerzeichen in Pfadnamen
  • Das Parsen des Leerraums des Mount ist problematisch. Die Manpage sagt jetzt:

Der Auflistungsmodus wird nur aus Gründen der Abwärtskompatibilität beibehalten.

Für eine robustere und anpassbarere Ausgabe verwenden Sie findmnt (8), insbesondere in Ihren Skripten.


Bash-Funktionen:

#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

Anwendungsbeispiele:

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
Elliptische Ansicht
quelle
1
Für Linux-spezifische ist dies der beste Ansatz. Ich habe den findmnt(8)Befehl gesehen, aber nie wirklich damit gespielt. Ehrlich gesagt, wenn ich einige meiner Skripte aktualisieren würde, die diese Art von Dingen ausführen (oder neue erstellen), wäre dies das, was ich tun würde.
Pryftan
1
Beachten Sie, dass für encfs findmntder Parameter angegeben werden muss --source encfs, andernfalls wird das anzuhängende Verzeichnis immer berücksichtigt, da es auf den übergeordneten Mount zurückgreift.
Burkart
Dies ist auch besser als die grepLösung , denn wenn ein Mount - Pfad seltsam ist, können Sie Fehlalarme auslösen: zB wenn ich mounten /dev/mmcblk0p1auf ~/mnt/dev/sda1, ich konnte nicht richtig , was /dev/sda1durch den Befehl montiert ist mount | grep '/dev/sda1'. Ich kann kein falsches positives Ergebnis erzielen findmnt. Gute Antwort!
Cody Piersall
7

Ein Skript wie dieses wird niemals portierbar sein. Ein schmutziges Geheimnis in Unix ist, dass nur der Kernel weiß, wo sich die Dateisysteme befinden, und abgesehen von Dingen wie / proc (nicht portabel) wird es Ihnen keine eindeutige Antwort geben.

Normalerweise benutze ich df, um herauszufinden, wo sich der Mount-Punkt eines Unterverzeichnisses befindet und in welchem ​​Dateisystem es sich befindet.

Zum Beispiel (erfordert eine Posix-Shell wie 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

Ein bisschen erzählt Ihnen nützliche Informationen.

chris
quelle
1
Die Frage ist mit Linux getaggt, also muss es vielleicht nicht portabel sein
Rory
6

Folgendes verwende ich in einem meiner Rsync-Backup-Cron-Jobs. Es überprüft, ob / backup aktiviert ist, und versucht, es zu aktivieren, wenn dies nicht der Fall ist.

HINWEIS: Das Folgende funktioniert nur unter Linux, da es greps / proc / mounts - eine portablere Version würde mount | ausführen grep / backup ', wie in Matthews Antwort ..

  wenn ! grep -q / backup / proc / mounts; dann
    wenn ! mount / backup; dann
      Echo "fehlgeschlagen"
      Ausfahrt 1
    fi
  fi
  Echo "erfolgreich".
  # hier Sachen machen
cas
quelle
2
Als gute Alternative zur Überprüfung der geistigen Gesundheit ausgezeichnet.
Dan Carley
Vermutlich stößt diese Methode auf die gleichen Probleme wie Matthew Blochs Antwort.
Mwfearnley
Ja, mit Ausnahme des in "Eliptical view" erwähnten Problems mit dem Leerzeichen im Dateinamen (dies greift die gesamte Zeile, nicht nur ein extrahiertes Feld). Das Sub-String-Problem ist keine große Sache, es sei denn, Sie vergessen irgendwie, dass Sie Argumente in Anführungszeichen setzen können. zB grep -q ' /backup ' /proc/mountsoder mount | grep -q ' /backup '. Oder Umleitung auf / dev / null , wenn Ihr grep nicht unterstützt -q(das ist in diesen Tagen in der POSIX - Spezifikation für grep).
cas
2

Da Sie zum Mounten ohnehin ein Verzeichnis benötigen, das gemountet wird, bestand meine Strategie immer darin, eine gefälschte Datei mit einem seltsamen Dateinamen zu erstellen, der niemals verwendet werden würde, und nur zu überprüfen, ob er existiert. Wenn die Datei dort war, wurde an dieser Stelle nichts gemountet ...

Ich denke nicht, dass dies für das Mounten von Netzwerklaufwerken oder ähnlichen Dingen funktioniert. Ich habe es für Flash-Laufwerke verwendet.

Brian Postow
quelle
2

Wie wäre es mit einem Vergleich der Gerätenummern? Ich habe nur versucht, über den esoterischsten Weg nachzudenken .

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

Da ist ein Fehler in meiner Logik ...

Als eine Funktion:

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

Die Echofehlermeldungen sind wahrscheinlich redundant, da stat ebenfalls einen Fehler anzeigt.

Kyle Brandt
quelle
Eigentlich müsste ich wahrscheinlich bei jedem Aufruf zuerst den Ausgangsstatus von stat überprüfen, um sicherzustellen, dass die Datei da ist ... nicht so neu, wie ich dachte :-(
Kyle Brandt
1

Keines dieser Verzeichnisse erfüllt den Anwendungsfall, bei dem ein bestimmtes Verzeichnis ein Unterverzeichnis innerhalb eines anderen Einhängepunkts ist. Zum Beispiel könnten Sie / thing haben, das ein NFS-Mount für den Host ist: / real_thing. Die Verwendung von grep für diesen Zweck unter / proc / mounts / etc / mtab oder 'mount' funktioniert nicht, da Sie nach einem Mount-Punkt suchen, der nicht existiert. Zum Beispiel ist / thing / thingy kein Mount-Punkt, aber / thing ist auf host gemountet: / real_thing. Die beste Antwort, über die hier abgestimmt wurde, ist NICHT "der beste Weg, um festzustellen, ob ein Verzeichnis / Volume eingehängt ist". Ich würde dafür stimmen, 'df -P' (-P POSIX-Standardmodus) als sauberere Strategie zu verwenden:

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

Die Ausgabe von diesem Programm ist:

Mounted via: host:/real_thing

Wenn Sie wissen möchten, wie hoch der tatsächliche Einhängepunkt ist, ist dies kein Problem:

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

Die Ausgabe dieses Befehls lautet:

Mounted on: /thing

Dies ist alles sehr nützlich, wenn Sie versuchen, eine Art Chroot zu erstellen, die Mount-Punkte außerhalb der Chroot innerhalb der Chroot über ein beliebiges Verzeichnis oder eine beliebige Dateiliste spiegelt.

Craig
quelle
1

Tut mir leid, dass ich das angesprochen habe, aber ich finde das ziemlich nützlich:

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

Dies ergibt die 2. Spalte von / proc / mounts (2. Spalte = Mountpunkte).

Dann greift es die Ausgabe. Beachten Sie die ^ und $, dies verhindert, dass / backup mit / mnt / backup oder / backup-old usw. übereinstimmt.

David
quelle
0

grep / etc / mtab für deinen mount point vielleicht?

Ophidian
quelle
1
mtab ist möglicherweise veraltet oder kann von mount einfach nicht aktualisiert werden, z. B. wenn Sie mount -n verwenden, weil / schreibgeschützt ist.
Chris
Ich stimme zu, aber das schien der erste Ort zu sein, an dem man nach etwas Ausschau halten sollte.
Ophidian
0

Diese?:

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

Von: Ein Ubuntu-Forum

RateControl
quelle
0

Obwohl dies eine Linux-Frage ist, warum sollte man es nicht portabel machen, wenn es einfach ist?

Die Manualpage von grepsagt:

Portable Shell-Skripte sollten sowohl -q als auch -s vermeiden und /dev/nullstattdessen Standard- und Fehlerausgaben an umleiten .

Also schlage ich folgende Lösung vor:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi
fex
quelle
3
Viele UNIX-Systeme bieten das / proc-Dateisystem nicht an
Dmitri Chubarov
@ DmitriChubarov In der Tat. Was macht das Konzept der Portabilität ironisch, nicht wahr? Und vielleicht ist es ein neueres Update aber -qund -swird von POSIX angegeben , so gibt es sowieso nicht damit jedes Portabilität Problem sein soll (jetzt wenn nicht schon vorher - ich habe nicht weiterverfolgen , welche Veränderungen geschehen , wenn).
Pryftan
0

Muss es noch komplizierter sein?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"
Matthew Bloch
quelle
1
grep -q /mnt/foopasst auch zu Mountpunkten /mnt/foodund /not/mnt/foo... Wie wäre es grep -qx /mnt/foo?
Rakslice
@rakslice: das würde nicht funktionieren. -xmacht grep match nur wenn die ganze Zeile passt.
mivk
1
cut -f 3 -d ' 'stolpert, wenn der Mount-Pfad ein Leerzeichen in einem Dateinamen enthält.
Elliptical View
0

Hängt davon ab, was Sie über die zu überprüfende Lautstärke wissen.

In dem speziellen Fall, in dem ich vor kurzem recherchiert habe, um herauszufinden, ob ein bestimmtes Flash-Laufwerk eingebunden ist, ist es am einfachsten, nach / dev / disks / by-label / zu suchen. Wenn das Gerät angeschlossen ist, stellen udev-Skripte sicher, dass der Link vorhanden ist (und dass er entfernt wird, wenn das Gerät nicht angeschlossen ist).

(Dies ist keine sehr portable Antwort. Sie funktioniert jedoch auf vielen modernen Linux-Distributionen. Die Frage wurde für Linux getaggt und unterscheidet sich grundlegend von den bisher genannten Ansätzen, sodass die Möglichkeiten erweitert werden.)

David Dyer-Bennet
quelle
0

Datei unter deinem Mountpoint erstellen check_mountund dann einfach testen ob es existiert?

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

Ich musste dies in Chef aus Idempotenz tun, da der Lauf, wenn Chef-Client ausgeführt wurde, aufgrund des bereits bereitgestellten Volumes fehlschlagen würde. Zum Zeitpunkt, an dem ich dies schreibe, hat die Chef- mountRessource einen Fehler, der bei Attributen nicht so funktioniert, wie ich es brauchte. Deshalb habe ich das Volume mithilfe der executeRessource bereitgestellt. So habe ich es gemacht:

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

Im Falle einer Verwechslung habe ich in meiner Attributdatei Folgendes:

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

Dies if not node['docker-server']['mountpoint'] == "none"ist ein Teil einer caseAnweisung, bei der der Mount-Punkt standardmäßig verwendet wird, wenn der Mount-Punkt auf dem Server nicht angegeben ist none.

KLaw
quelle
... und was hat das mit der ursprünglichen Frage zu tun?!?
Massimo
Die Beziehung meines Chefkoch-Rezeptkommentars zur ursprünglichen Frage ist, dass sich die Menschen zunehmend in Richtung Automatisierung bewegen. Wenn jemand hierher kommt und sich fragt, wie das in einem Kochrezept funktioniert, hat er eine Antwort. Im Leben gibt es zwei Möglichkeiten: 1) Das Nötigste tun und einige Menschen glücklich machen, und 2) Die Extrameile gehen. Anstatt meinen Beitrag zu markieren, akzeptieren Sie ihn daher für das, was er ist: Zusätzliche Informationen, die die akzeptierte Antwort unterstützen.
KLaw,
Die Frage betraf Bash-Skripte, Ihre Antwort betraf Chef-Skripte. Während es möglicherweise für jemanden nützlich sein könnte, hat es dennoch keine Relevanz für die Frage.
Massimo
@KLaw 'Anstatt meinen Beitrag zu markieren, akzeptieren Sie ihn als den, was er ist: zusätzliche Informationen, die die akzeptierte Antwort unterstützen.' Ich bin damit einverstanden und nicht einer, der normalerweise abstimmt (und ich auch nicht), aber wenn Sie ein Problem mit dieser Art von Dingen haben, sollten Sie es vielleicht als Ergänzung zu Ihren anderen Punkten hinzufügen? Könnte die anderen Kommentare speichern. Aber was die Automatisierung angeht, so ist es genau das, was Bash-Skripte zulassen, sodass ich Ihren Standpunkt nicht verstehe. Natürlich denkt der Programmierer in mir, dass das obige Skript abscheulich ist, aber das ist mehr als alles andere ein Sprachproblem ...
Pryftan