¿Cómo puedo verificar si un volumen está montado donde se supone que está usando Python?

9

Tengo un script de copia de seguridad escrito en Python que crea el directorio de destino antes de copiar el directorio de origen. Lo configuré para usarlo /external-backupcomo destino, que es donde monte un disco duro externo. Simplemente ejecuté el script sin que el disco duro se encendiera (o se montara) y descubrí que funcionaba normalmente, aunque hice una copia de seguridad en el disco duro interno, que no tiene espacio suficiente para hacer una copia de seguridad.

Mi pregunta es: ¿cómo puedo verificar si el volumen está montado en el lugar correcto antes de escribir en él? Si puedo detectar que /external-backupno está montado, puedo evitar escribir en él.

La pregunta adicional es por qué se permitió esto, cuando el sistema operativo sabe que se supone que el directorio debe vivir en otro dispositivo, y ¿qué sucedería con los datos (en el disco duro interno)? ¿Debería montar ese dispositivo (el disco duro externo)? ¡Claramente no puede haber dos copias en diferentes dispositivos en la misma ruta!

¡Gracias por adelantado!

Ben Hymers
fuente

Respuestas:

22

Lo echaría un vistazo os.path.ismount().

Pausado hasta nuevo aviso.
fuente
1
El único problema es que devuelve un valor booleano y no especifica si el dispositivo correcto está allí.
McJeff
3
@ McJeff: Eso es cierto, no dice cuál dice si . Si no hay ningún dispositivo allí, devolverá falso y una escritura en esa ruta escribirá en el directorio subyacente en el sistema de archivos principal . Entonces, si devuelve falso, emita un error y no escriba allí. El directorio /external-backupno vive en un dispositivo externo, vive en el sistema de archivos principal. El sistema solo sabe lo que mountle dice, no tiene idea de lo que debería estar allí. No hay nada especial sobre un "punto de montaje" en un sistema de archivos Unix. Es solo un directorio regular.
Pausado hasta nuevo aviso.
Eso hace el trabajo perfectamente. No voy a proteger contra otros volúmenes que se montan allí, solo que no es el sistema de archivos principal. Lo siento para los otros respondedores, sus respuestas pueden responder mi pregunta más exactamente, pero me temo que no sabía qué pedir en primer lugar, como podría decir;) Los he calificado a todos de todos modos .
Ben Hymers
¡Buena explicación!
McJeff
5

Para obtener una respuesta definitiva a algo que solo el núcleo sabe con certeza, pregúntele al núcleo:

cat /proc/mounts

Ese archivo se puede leer / analizar como si fuera un archivo normal, utilizando cualquier herramienta que desee. Incluyendo Python. Ejemplo rápido y sucio:

#!/usr/bin/python

d = {}

for l in file('/proc/mounts'):
    if l[0] == '/':
        l = l.split()
        d[l[0]] = l[1]

import pprint

pprint.pprint(d)
Insyte
fuente
4

La forma más fácil de verificar es invocar a mounttravés de subprocessy ver si aparece allí. Para obtener crédito adicional, úselo os.readlink()en el contenido de /dev/disk/by-*para averiguar qué dispositivo es.

Ignacio Vazquez-Abrams
fuente
Según lo veo, el problema con ese enfoque es que la salida de mountse define descuidadamente en el mejor de los casos. ¿Qué da mountsalida si he montado /dev/evil device on touren /directory on which I mount devices? El análisis de la producción podría ser poco fiable en estos casos ...
Skyking
2

Bonus de respuesta. Si el dispositivo externo no está montado, los datos se escriben en la partición raíz en la ruta /external-backup. Si el dispositivo externo está montado, los datos en la partición raíz aún están allí, pero no es accesible porque /external-backupahora apunta a un dispositivo externo.

Codificador casual
fuente
2

Antigua pregunta, pero pensé que contribuiría con mi solución (basada en la respuesta de Dennis Williamson e Ignacio Vázquez-Abrams ) de todos modos. Como lo estoy usando en un entorno que no es Linux para verificar los directorios remotos que se están montando, / proc y mtab no se pueden usar y no se han implementado verificaciones adicionales:

def is_mounted(special, directory):
    search_prefix = '{} on {}'.format(special, directory.rstrip('/'))

    if os.path.ismount(directory):
        mounts = subprocess.check_output(['mount']).split('\n')

        for line in mounts:
            if line[:len(search_prefix)] == search_prefix:
                return True;

    return False

¡Mejoras bienvenidas!

Magentron
fuente
1

El archivo / etc / mtab existe para decirle lo que está montado actualmente. Hay una getmntentllamada, pero no creo que se exporte en el osmódulo. ¿El rápido y sucio? Abra / etc / mtab y divida. Asegúrese de que su dispositivo esté presente en la columna 0 y que el punto de montaje de destino en la columna 1 sea correcto.

McJeff
fuente