Quel est le meilleur moyen de vérifier si un volume est monté dans un script Bash?

103

Quel est le meilleur moyen de vérifier si un volume est monté dans un script Bash?

Ce que j'aimerais vraiment, c'est une méthode que je peux utiliser comme ceci:

if <something is mounted at /mnt/foo> 
then
   <Do some stuff>
else
   <Do some different stuff>
fi
Mark Biek
la source
J'étais sur le point d'écrire un script pour le faire moi-même. Ma première pensée est d’obtenir des informations de / etc / mtab. Mais je n’ai pas encore feuilleté mes livres de bash pour voir s’il existe un moyen plus direct.
3dinfluence
@ 3dinfluence - oui, je le sais depuis très longtemps, mais /etc/mtab, /proc/mountssont liés à /proc/self/mounts. (au moins sur Fedora 20 il est)
Wilf
Des questions similaires se posent sur Server Fault , Stack Overflow et Unix & Linux Stack Exchange .
Sasha

Réponses:

113

Évitez d'utiliser /etc/mtabparce que cela peut être incohérent.

Évitez les tuyaux mountcar ils ne doivent pas nécessairement être compliqués.

Simplement:

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

(L'espace après le /mnt/fooest d'éviter de faire correspondre par exemple /mnt/foo-bar.)

Dan Carley
la source
7
Sans oublier, un appel à monter peut être suspendu si le point de montage est bloqué.
Chad Huneycutt
8
Bon pour Linux, pas pour FreeBSD ou Solaris.
chris
4
C'est vrai, chris. Bien que la question a été étiquetée linux.
Dan Carley
3
J'imagine que c'est une question philosophique - devrions-nous essayer de rendre les choses portables si possible ou devrions-nous simplement supposer que tout le monde tourne sous Windows / Linux et agir en conséquence?
chris
18
En fait, vous devriez tester '/ mnt / foo', c'est-à-dire. avec un espace ou vous pourriez obtenir un faux positif si vous aviez monté un volume nommé par exemple. "Fooks". Je viens d'avoir ce problème avec deux points de montage, «lmde» et «lmde-home».
Mars
58
if mountpoint -q /mnt/foo 
then
   echo "mounted"
else
   echo "not mounted"
fi

ou

mountpoint -q /mnt/foo && echo "mounted" || echo "not mounted"
Zaptac
la source
4
Juste pour information: mountpointprovient du paquet "initscripts" dans Ubuntu / Debian.
blueyed
1
Ca n'a pas marché pour moi - :-(
Wilf
C'est l'appel auquel mon vagabond se cramponne.
dhill
Le problème mountpointest qu’il vérifie, en fait, si un point de montage est monté, mais pas si un périphérique est monté. Si un périphérique est passé avec l' -xoption, il vous indique le numéro de périphérique majeur / mineur, mais pas s'il est monté.
Vegatripy
@blueyed Dans Debian Buster, il est fourni par le paquetutil-linux
elboulangero
18

findmnt -rno SOURCE,TARGET "$1"évite tous les problèmes dans les autres réponses. Il fait proprement le travail avec une seule commande.


D'autres approches ont ces inconvénients:

  • grep -qet grep -ssont une étape supplémentaire inutile et ne sont pas pris en charge partout.
  • /proc/\* n'est pas supporté partout.
  • mountinfo est basé sur / proc / ..
  • cut -f3 -d' ' gâche les espaces dans les noms de chemins
  • L'analyse de l' espace blanc de mount pose problème. C'est la page de manuel qui dit maintenant:

Le mode liste est maintenu pour la compatibilité ascendante uniquement.

Pour une sortie plus robuste et personnalisable, utilisez findmnt (8), en particulier dans vos scripts.


Fonctions 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

Exemples d'utilisation:

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
Vue elliptique
la source
1
Pour Linux en tout cas, c’est la meilleure approche. J'ai vu la findmnt(8)commande mais je n'ai jamais vraiment joué avec. Franchement, si je mettais à jour certains de mes scripts qui font ce genre de choses (ou en créons de nouveaux) sur une machine Linux (ou lorsque la commande est disponible), c’est ce que je ferais.
Pryftan
1
Notez que pour encfs, findmntdoit être fourni avec le paramètre --source encfs, sinon il considérera toujours que le répertoire est monté car il revient au montage parent.
Burkart le
Ceci est également meilleur que la grepsolution car si un chemin de montage est étrange, vous pouvez obtenir des faux positifs: par exemple, si je monte /dev/mmcblk0p1dessus ~/mnt/dev/sda1, je risque de ne pas utiliser la chose /dev/sda1montée par la commande mount | grep '/dev/sda1'. Je ne peux pas obtenir un faux positif en utilisant findmnt. Bonne réponse!
Cody Piersall
7

Un script comme celui-ci ne sera jamais portable. Un sale secret sous Unix est que seul le noyau sait quels systèmes de fichiers se trouvent où et, à part des choses comme / proc (non portable), il ne vous donnera jamais de réponse directe.

J'utilise généralement df pour découvrir le point de montage d'un sous-répertoire et son système de fichiers.

Par exemple (nécessite un shell posix comme cendres / 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

Kinda vous dit des informations utiles.

chris
la source
1
La question est étiquetée linux, alors peut-être que ça n'a pas besoin d'être portable
Rory
6

Voici ce que j'utilise dans l'un de mes travaux cron de sauvegarde rsync. il vérifie si / backup est monté et essaie de le monter s'il ne l'est pas (cela peut échouer car le lecteur se trouve dans une baie remplaçable à chaud et peut même ne pas être présent dans le système)

NOTE: Ce qui suit ne marche que sur linux, car il contient greps / proc / mounts - une version plus portable exécutera 'mount | grep / backup ', comme dans la réponse de Matthew ..

  si ! grep -q / backup / proc / mounts; ensuite
    si ! monter / sauvegarder; ensuite
      echo "échoué"
      sortie 1
    Fi
  Fi
  echo "réussi"
  # faire des choses ici
cas
la source
2
Upvoté comme une alternative bonne vérification de la santé mentale.
Dan Carley
Vraisemblablement, cette méthode se heurte aux mêmes problèmes que la réponse de Matthew Bloch.
mwfearnley
Oui, à l'exception du problème d'espace dans le nom de fichier mentionné par "Eliptical view" (ceci insère toute la ligne, pas seulement un champ extrait). Le problème des sous-chaînes n’est pas un problème, sauf si vous oubliez que citer des arguments est une chose que vous pouvez faire. par exemple grep -q ' /backup ' /proc/mountsou mount | grep -q ' /backup '. Ou redirigez vers / dev / null si votre grep ne supporte pas -q(ce qui est dans les spécifications POSIX pour grep de nos jours).
cas
2

Comme pour monter, vous devez de toute façon avoir un répertoire, qui est monté dessus, ma stratégie a toujours été de créer un faux fichier avec un nom de fichier étrange qui ne serait jamais utilisé, et juste de vérifier son existence. Si le fichier était là, rien n'était monté à cet endroit ...

Je ne pense pas que cela fonctionne pour monter des lecteurs réseau ou des choses comme ça. Je l'ai utilisé pour les lecteurs flash.

Brian Postow
la source
2

Que diriez-vous de comparer les numéros d'appareils? J'essayais juste de penser à la manière la plus ésotérique ..

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

Il y a un défaut dans ma logique avec ça ...

En tant que fonction:

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

Les messages d'erreur echo sont probablement redondants, car stat affichera également une erreur.

Kyle Brandt
la source
En fait, il faudrait probablement vérifier l’état de sortie de stat d’abord pour chaque appel afin de s’assurer que le fichier est là ... pas aussi nouveau que je le pensais :-(
Kyle Brandt
1

Aucune de celles-ci ne convient au cas d'utilisation où un répertoire donné est un sous-répertoire dans un autre point de montage. Par exemple, vous pourriez avoir / thing qui est un montage NFS à héberger: / real_thing. Utiliser grep à cette fin sur / proc / mounts / etc / mtab ou 'mount' ne fonctionnera pas, car vous rechercherez un point de montage qui n'existe pas. Par exemple, / thing / thingy n'est pas un point de montage, mais / thing est monté sur l'hôte: / real_thing. La meilleure réponse mise ici n'est pas "le meilleur moyen de déterminer si un répertoire / volume est monté". Je voterais en faveur de l'utilisation de 'df -P' (mode standard -P POSIX) comme stratégie plus propre:

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

Le résultat de l’exécution sera:

Mounted via: host:/real_thing

Si vous voulez savoir quel est le véritable point de montage, pas de problème:

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

Le résultat de cette commande sera:

Mounted on: /thing

Ceci est très utile si vous essayez de créer une sorte de chroot qui reflète les points de montage en dehors du chroot, au sein du chroot, via un répertoire ou une liste de fichiers arbitraire.

Craig
la source
1

Désolé d'avoir soulevé cette question, mais je pense que c'est très utile:

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

Cela donne la 2e colonne de / proc / mounts (2e colonne = points de montage).

Ensuite, il affiche la sortie. Notez que ^ et $, cela empêche / backup de faire correspondre / mnt / backup ou / backup-old etc.

David
la source
0

grep / etc / mtab pour votre point de montage peut-être?

Ophidien
la source
1
mtab peut devenir obsolète ou simplement ne pas être mis à jour par mount, comme lorsque vous utilisez mount -n car / est en lecture seule.
chris
Je suis d'accord, mais cela semblait être le premier endroit à commencer à chercher.
Ophidian
0

Cette?:

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

De: un forum Ubuntu

RateControl
la source
0

Bien que ce soit une question Linux, pourquoi ne pas le rendre portable quand il est facile à faire?

La page de manuel de grepdit:

Les scripts de shell portables devraient éviter à la fois les options -q et -s et devraient /dev/nullplutôt rediriger les sorties standard et d'erreur .

Je propose donc la solution suivante:

if grep /mnt/foo /proc/mounts > /dev/null 2>&1; then
        echo "Mounted"
else
        echo "NOT mounted"
fi
fex
la source
3
De nombreux systèmes UNIX ne fournissent pas le système de fichiers / proc
Dmitri Chubarov
@ Dimitri Chubarov En effet. Ce qui rend le concept de portabilité ironique, n'est-ce pas? Et peut - être que c'est une mise à jour plus récente , mais -qet -ssont spécifiés par POSIX donc il ne devrait pas y avoir de problème de portabilité avec elle de toute façon (maintenant sinon avant - je ne l' ai pas gardé la trace des changements qui se produit quand).
Pryftan
0

Cela doit-il être plus compliqué que cela?

mount \
    | cut -f 3 -d ' ' \
    | grep -q /mnt/foo \
  && echo "mounted" || echo "not mounted"
Matthew Bloch
la source
1
grep -q /mnt/foosera également correspondre à des points de montage /mnt/foodet /not/mnt/foo... Que diriez-vous grep -qx /mnt/foo?
Rakslice
@rakslice: ça ne marcherait pas. -xfait correspondre grep uniquement si la ligne entière correspond.
mardi
1
cut -f 3 -d ' 'trébuche quand le chemin de montage a un espace dans un nom de fichier.
Vue elliptique
0

Tout dépend de ce que vous savez sur le volume que vous recherchez.

Dans le cas particulier que j'ai étudié récemment, où je me demandais si un lecteur flash particulier était monté, ce qui fonctionne le plus facilement est de vérifier l'existence de / dev / disks / by-label /. Si le périphérique est branché, les scripts udev s'assurent que le lien existe (et qu'il est supprimé lorsque le périphérique est débranché).

(Ce n'est PAS une réponse très portable; cela fonctionne sur de nombreuses distributions Linux modernes, cependant, et la question a été étiquetée pour Linux, et c'est une approche complètement différente de tout ce qui a été mentionné jusqu'ici, de sorte qu'elle élargit les possibilités.)

David Dyer-Bennet
la source
0

Créer un fichier sous votre point de montage comme check_mountet ensuite juste tester s'il existe?

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

Je devais le faire dans Chef pour idempotence car, lorsque chef-client s'exécutait, l'exécution échouait en raison du volume déjà monté. Au moment où j'écris ceci, la mountressource Chef avait une sorte de bogue qui ne fonctionnait pas avec les attributs comme je le souhaitais. J'ai donc monté le volume à l'aide de la executeressource. Voici comment je l'ai fait:

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

En cas de confusion, dans mon fichier d'attributs, j'ai les éléments suivants:

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

Le if not node['docker-server']['mountpoint'] == "none"fait partie d'une caseinstruction où, si le point de montage sur le serveur n'est pas spécifié, le point de montage par défaut est none.

KLaw
la source
... et qu'est-ce que cela a à voir avec la question initiale?!?
Massimo
La relation entre ma recette de chef et la question initiale est que les gens s'orientent de plus en plus vers l'automatisation. Par conséquent, si quelqu'un vient ici se demander comment utiliser cette recette dans une recette de Chef, il aura une réponse. Dans la vie, il y a deux options: 1) faire le strict minimum et rendre certaines personnes heureuses, et 2) faire un effort supplémentaire. Par conséquent, au lieu de marquer mon message, acceptez-le pour ce qu'il est: des informations supplémentaires qui prennent en charge la réponse acceptée.
KLaw
La question portait sur les scripts bash, votre réponse porte sur les scripts Chef. Bien que cela puisse être utile à quelqu'un, cela n'a toujours aucun rapport avec la question.
Massimo
@KLaw 'Par conséquent, au lieu de marquer mon message, acceptez-le pour ce qu'il est: des informations supplémentaires qui prennent en charge la réponse acceptée.' Je suis d’accord et je ne suis pas du genre à voter habituellement (et je n’ai pas été ici non plus), mais si vous rencontrez un problème avec ce type de problème, vous devriez peut-être l’ajouter à vos autres points? Peut sauver les autres commentaires. Mais en ce qui concerne l’automatisation, c’est exactement ce que permettent les scripts bash, je ne vois donc pas votre argument. Bien sûr, le programmeur en moi pense que le script ci-dessus est hideux, mais c'est un problème de langue plus que toute autre chose ...
Pryftan