¿Cuál es la mejor manera de verificar si un volumen está montado en un script Bash?


103

¿Cuál es la mejor manera de verificar si un volumen está montado en un script Bash?

Lo que realmente me gustaría es un método que pueda usar así:

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

Estaba a punto de escribir un guión para hacer esto yo mismo. Mi primer pensamiento es obtener información de / etc / mtab Pero aún no he hojeado mis libros de bash para ver si hay una forma más directa.
3dinfluence

@ 3dinfluence - sí sé esto desde hace mucho tiempo, pero /etc/mtab, /proc/mountsestán vinculados a /proc/self/mounts. (al menos en Fedora 20 es)
Wilf

Preguntas similares se encuentran en Falla del servidor , Desbordamiento de pila y Intercambio de pila de Unix y Linux .
Sasha

Respuestas:


113

Evite usarlo /etc/mtabporque puede ser inconsistente.

Evite las tuberías mountporque no tiene por qué ser tan complicado.

Simplemente:

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

(El espacio después del /mnt/fooes para evitar coincidencias, por ejemplo /mnt/foo-bar).


77
Sin mencionar que una llamada al montaje puede colgarse si el punto de montaje está en cuña.
Chad Huneycutt

8
Bueno para linux, no para freebsd o solaris.
Chris

44
Esto es verdad, Chris. Aunque la pregunta fue etiquetada linux.
Dan Carley

3
Supongo que esta es una pregunta filosófica: ¿deberíamos intentar hacer que las cosas sean portátiles si es posible o deberíamos asumir que todas las ventanas / linux del mundo funcionan y actuar en consecuencia?
Chris

18
En realidad, debe probar '/ mnt / foo', es decir. con un espacio o podría obtener un falso positivo si hubiera montado un volumen llamado eg. 'fooks'. Acabo de recibir ese problema con dos puntos de montaje, 'lmde' y 'lmde-home'.
marlar

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

o

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

44
Solo para información: se mountpointorigina en el paquete "initscripts" en Ubuntu / Debian.
azulado

1
No funcionó para mí - :-(
Wilf

Esta es la llamada, de la que depende mi Vagabundo.
dhill

El problema mountpointes que comprueba, de hecho, si se monta un punto de montaje, pero no si se monta un dispositivo. Si se pasa un dispositivo con la -xopción, le indica el número de dispositivo mayor / menor, pero no si está montado.
vegatripy

@blueyed En Debian Buster lo proporciona el paqueteutil-linux
elboulangero

18

findmnt -rno SOURCE,TARGET "$1"evita todos los problemas en las otras respuestas. Limpiamente hace el trabajo con solo un comando.


Otros enfoques tienen estos inconvenientes:

  • grep -qy grep -sson un paso innecesario adicional y no son compatibles en todas partes.
  • /proc/\* no es compatible en todas partes.
  • mountinfo se basa en / proc / ..
  • cut -f3 -d' ' desordena los espacios en los nombres de ruta
  • Analizar el espacio en blanco del soporte es problemático. Su página de manual ahora dice:

.. el modo de listado se mantiene solo para compatibilidad con versiones anteriores.

Para una salida más robusta y personalizable, use findmnt (8), especialmente en sus scripts.


Funciones 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

Ejemplos de uso:

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
Para Linux, de todos modos, este es realmente el mejor enfoque. He visto el findmnt(8)comando pero nunca jugué con él. Francamente, si tuviera que actualizar algunos de mis scripts que hacen este tipo de cosas (o hacer nuevos) en una caja de Linux (o donde el comando está disponible), esto es lo que haría.
Pryftan

1
Tenga en cuenta que para encfs, findmntdebe suministrarse con el parámetro --source encfs; de lo contrario, siempre considerará que el directorio se debe montar, ya que recae en el montaje principal.
Burkart

Esta es también mejor que la grepsolución porque si una ruta de montaje es raro, puede obtener falsos positivos: por ejemplo, si puedo montar /dev/mmcblk0p1en ~/mnt/dev/sda1, pude incorrectamente cosa que /dev/sda1se monta por el comando mount | grep '/dev/sda1'. No puedo obtener un falso positivo usando findmnt. ¡Buena respuesta!
Cody Piersall

7

Una secuencia de comandos como esta nunca será portátil. Un secreto sucio en Unix es que solo el núcleo sabe dónde están los sistemas de archivos y, a falta de cosas como / proc (no portátil), nunca le dará una respuesta directa.

Normalmente uso df para descubrir cuál es el punto de montaje de un subdirectorio y en qué sistema de archivos se encuentra.

Por ejemplo (requiere shell posix como 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

Un poco te dice información útil.


1
La pregunta está etiquetada con Linux, así que tal vez no tiene que ser portátil
Rory

6

Lo siguiente es lo que uso en uno de mis trabajos cron de copia de seguridad rsync. comprueba si está montado / copia de seguridad e intenta montarlo si no lo está (puede fallar porque la unidad está en una bahía de intercambio en caliente y puede que ni siquiera esté presente en el sistema)

NOTA: lo siguiente solo funciona en Linux, porque greps / proc / monta - una versión más portátil ejecutaría 'mount | grep / backup ', como en la respuesta de Matthew ...

  Si ! grep -q / backup / proc / mounts; entonces
    Si ! montaje / respaldo; entonces
      echo "fallido"
      salida 1
    fi
  fi
  echo "tuvo éxito".
  # haz cosas aquí

2
Elegido como una buena alternativa para controlar la cordura.
Dan Carley

Presumiblemente, este método se encuentra con los mismos problemas que la respuesta de Matthew Bloch.
mwfearnley

sí, excepto por el problema del espacio en el nombre de archivo mencionado por "Vista elíptica" (esto agrupa toda la línea, no solo un campo extraído). El problema de la subcadena no es gran cosa a menos que de alguna manera olvides que citar argumentos es algo que puedes hacer. por ejemplo grep -q ' /backup ' /proc/mountso mount | grep -q ' /backup '. O redirigir a / dev / null si su grep no es compatible -q(que está en la especificación POSIX para grep en estos días).
cas

2

Dado que para montar, debe tener un directorio allí de todos modos, que se monta, mi estrategia siempre fue crear un archivo falso con un nombre de archivo extraño que nunca se usaría, y simplemente verificar su existencia. Si el archivo estaba allí, entonces no se montó nada en ese lugar ...

No creo que esto funcione para montar unidades de red o cosas así. Lo usé para unidades flash.


2

¿Qué tal comparar números de dispositivos? Solo estaba tratando de pensar en la forma más esotérica ...

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

Hay un defecto en mi lógica con eso ...

Como una función:

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

Los mensajes de error de eco probablemente sean redundantes, ya que stat también mostrará el error.


En realidad, probablemente tendría que verificar el estado de salida de stat primero para cada llamada para asegurarse de que el archivo esté allí ... no tan novedoso como pensé :-(
Kyle Brandt

1

Ninguno de estos satisface el caso de uso donde un directorio dado es un subdirectorio dentro de otro punto de montaje. Por ejemplo, puede tener / thing, que es un montaje NFS para alojar: / real_thing. Usar grep para este propósito en / proc / mounts / etc / mtab o 'mount' no funcionará, porque buscará un punto de montaje que no exista. Por ejemplo, / thing / thingy no es un punto de montaje, pero / thing está montado en el host: / real_thing. La mejor respuesta votada aquí en realidad NO es "la mejor manera de determinar si un directorio / volumen está montado". Votaría a favor usando 'df -P' (modo de estándares -P POSIX) como una estrategia más limpia:

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

El resultado de ejecutar esto será:

Mounted via: host:/real_thing

Si quieres saber cuál es el punto de montaje real, no hay problema:

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

El resultado de ese comando será:

Mounted on: /thing

Todo esto es muy útil si está intentando crear algún tipo de chroot que refleje los puntos de montaje fuera del chroot, dentro del chroot, a través de un directorio arbitrario o una lista de archivos.


1

Perdón por mencionar esto, pero creo que esto es bastante útil:

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

Esto obtiene la segunda columna de / proc / monturas (segunda columna = puntos de montaje).

Luego, greps la salida. Tenga en cuenta ^ y $, esto evita que / backup coincida con / mnt / backup o / backup-old, etc.


0

grep / etc / mtab para su punto de montaje, tal vez?


1
mtab puede estar desactualizado o simplemente no ser actualizado por mount, como cuando usa mount -n porque / es de solo lectura.
Chris

Estoy de acuerdo, pero ese parecía ser el primer lugar para comenzar a buscar.
Ophidian


0

Aunque esta es una pregunta de Linux, ¿por qué no hacerlo portátil cuando se hace fácilmente?

La página del manual de grepdice:

Los scripts de shell portátiles deberían evitar tanto -q como -s y deberían redirigir la salida estándar y la salida de error a su /dev/nulllugar.

Por eso propongo la siguiente solución:

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

3
Muchos sistemas UNIX no proporcionan el sistema de archivos / proc
Dmitri Chubarov

@DmitriChubarov De hecho. Lo que hace que el concepto de portabilidad sea irónico, ¿no? Y tal vez es una actualización más reciente, pero -qy -sse especifican por POSIX por lo que no debería haber ningún problema con la portabilidad de todos modos (ahora si no antes - yo no he mantenido un registro de qué cambios ocurren cuando).
Pryftan

0

¿Tiene que ser más complicado que esto?

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

1
grep -q /mnt/footambién coincidirá con los puntos de montaje /mnt/foody /not/mnt/foo... ¿Qué tal grep -qx /mnt/foo?
rakslice

@rakslice: eso no funcionaría. -xhace que grep coincida solo si la línea completa coincide.
mivk

1
cut -f 3 -d ' 'tropieza cuando la ruta de montaje tiene un espacio en un nombre de archivo.
Vista elíptica

0

Depende de lo que sepa sobre el volumen que está buscando.

En el caso particular que investigué recientemente, donde me preocupaba encontrar si se montó una unidad flash en particular, lo que funciona más fácilmente es verificar la existencia de / dev / disks / by-label /. Si el dispositivo está enchufado, los scripts de udev aseguran que el enlace exista (y que se elimine cuando el dispositivo esté desconectado).

(Esta NO es una respuesta altamente portátil; sin embargo, funciona en muchas distribuciones modernas de Linux, y la pregunta fue etiquetada para Linux, y es un enfoque completamente diferente de todo lo mencionado hasta ahora, por lo que amplía las posibilidades).


0

¿Crear un archivo debajo de su punto de montaje como check_mounty luego probar si existe?

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

-1

Tuve que hacer esto en Chef por idempotencia ya que cuando el chef-cliente se ejecutaba, la ejecución fallaba debido al volumen ya montado. En el momento en que escribo esto, el mountrecurso Chef tiene algún tipo de error que no funcionaría con los atributos de la manera que lo necesitaba, por lo que monté el volumen usando el executerecurso. Así es como lo hice:

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 caso de confusión, en mi archivo de atributos, tengo lo siguiente:

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

El if not node['docker-server']['mountpoint'] == "none"es una parte de una casedeclaración en la que si no se especifica el punto de montaje en el servidor, el punto de montaje está predeterminado none.


... y ¿qué tiene esto que ver con la pregunta original?
Massimo

La relación del comentario de mi receta Chef con la pregunta original es que las personas se están moviendo cada vez más hacia la automatización. Por lo tanto, si alguien viene aquí preguntándose cómo hacer que esto funcione en una receta de Chef, tendrá una respuesta. En la vida hay dos opciones: 1) Hacer lo mínimo y hacer felices a algunas personas, y 2) Hacer un esfuerzo adicional. Por lo tanto, en lugar de marcar mi publicación, acéptela por lo que es: información adicional que respalde la respuesta aceptada.
KLaw

La pregunta era sobre los scripts de bash, su respuesta es sobre los scripts de Chef. Si bien podría ser útil para alguien, aún no tiene ninguna relevancia para la pregunta.
Massimo

@KLaw 'Por lo tanto, en lugar de marcar mi publicación, acéptela por lo que es: información adicional que respalde la respuesta aceptada'. Estoy de acuerdo y no soy de los que suelen rechazar el voto (y tampoco lo he hecho aquí), pero si tienes un problema con ese tipo de cosas, ¿deberías agregarlo como una adición a tus otros puntos? Podría guardar los otros comentarios. Pero en cuanto a la automatización, eso es exactamente lo que permiten los scripts de bash, por lo que no veo su punto. Por supuesto, el programador en mí piensa que el guión anterior es horrible, pero eso es un problema de lenguaje más que cualquier otra cosa ...
Pryftan
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.