2011-10-10 13 views
5

¿Cómo se usa Python para determinar qué dispositivo/partición Linux contiene un sistema de archivos determinado?Determinar el dispositivo del sistema de archivos en Python

p. Ej.

>>> get_filesystem_device('/') 
/dev/sda 
>>> get_filesystem_partition('/') 
/dev/sda1 
+1

por qué no tratar de analizar la salida de 'mount'? –

Respuesta

0

no es el purdiest, pero esto le ayudará a empezar:

#!/usr/bin/python 

import os, stat, subprocess, shlex, re, sys 

dev=os.stat('/')[stat.ST_DEV] 
major=os.major(dev) 
minor=os.minor(dev) 

out = subprocess.Popen(shlex.split("df /"), stdout=subprocess.PIPE).communicate() 
m=re.search(r'(/[^\s]+)\s',str(out)) 

if m: 
    mp= m.group(1) 
else: 
    print "cannot parse df" 
    sys.exit(2) 

print "'/' mounted at '%s' with dev number %i, %i" % (mp,major,minor) 

En OS X:

'/' mounted at '/dev/disk0s2' with dev number 14, 2 

En Ubuntu:

'/' mounted at '/dev/sda1' with dev number 8, 1 

Para obtener el nombre del dispositivo, cortar el número menor del nombre de la partición. En OS X, también corta el número 's' + menor.

1

Parece que este post no tiene algunos de su respuesta (todavía seguro de cómo para agarrar la mayor/menor de la entrada /dev/sda2 para que coincida con lo que os.stat() devoluciones para /:

Device number in stat command output

>>> import os 
>>> print hex(os.stat('/')[2]) 
0x802 
    \ \minor device number 
    \major device number 

[[email protected] /]$ ls -l /dev/sda2 
brw-rw---- 1 root  disk  8, 2 Jun 24 2004 /dev/sda2 
[[email protected] jgaines2]$    \ \minor device number 
            \major device number 
+0

Puede analizar/proc/partitions para mapear maj/min para nombrar. –

+0

me gustó mucho esta respuesta, por lo que he estado buscando hasta cómo obtener la inversa para encontrar/dev/sda2 (en el ejemplo). En lugar de análisis sintáctico/proc/particiones, puede recorrer a través de/dev/y encontrar el archivo que tiene un dev st_rdev correspondiente (nombre sugerente, "dev inversa" coincide con "dev" :) os.stat ('/'). Dev_t = = os.stat ('/ dev/sda1'). st_rdev –

+0

Esto también es mejor que mirar/proc/mounts (como en otras respuestas) como PI frambuesa (por ejemplo) tiene/dev/root como el montaje de "/ "a pesar de que la salida del comando" mount "proporciona el archivo del dispositivo/dev/mmc * correcto. –

2

Su pregunta era acerca de Linux, por lo que esto es (más o menos) específico de Linux.

A continuación se muestra un ejemplo de código para tres variantes para mapear mayor/menor a un nombre de dispositivo.

  • Parse/proc/partitions.
  • Preguntar hal. Hal también realiza un seguimiento del dispositivo "principal", lo que significa que puede obtener fácilmente el disco y también la partición.
  • Compruebe sysfs usted mismo. Aquí es de donde hal obtiene su información.

Yo diría que/proc/partitions es el más simple: es solo un archivo para abrir y verificar. Hal le brinda la mayor información y abstrae muchos detalles. sysfs puede verse como más correcto que/proc/partitions y no requiere que hal se ejecute.

Para un programa de escritorio me gustaría ir a hal. En un sistema integrado, iría con sysfs.


import os 

def main(): 
    dev = os.stat("/home/").st_dev 
    major, minor = os.major(dev), os.minor(dev) 

    print "/proc/partitions says:", ask_proc_partitions(major, minor) 
    print "HAL says:", ask_hal(major, minor) 
    print "/sys says:", ask_sysfs(major, minor) 

def _parse_proc_partitions(): 
    res = {} 
    for line in file("/proc/partitions"): 
     fields = line.split() 
     try: 
      tmaj = int(fields[0]) 
      tmin = int(fields[1]) 
      name = fields[3] 
      res[(tmaj, tmin)] = name 
     except: 
      # just ignore parse errors in header/separator lines 
      pass 

    return res 

def ask_proc_partitions(major, minor): 
    d = _parse_proc_partitions() 
    return d[(major, minor)] 

def ask_hal(major, minor): 
    import dbus 

    bus = dbus.SystemBus() 
    halobj = bus.get_object('org.freedesktop.Hal', '/org/freedesktop/Hal/Manager') 
    hal = dbus.Interface(halobj, 'org.freedesktop.Hal.Manager') 

    def getdevprops(p): 
     bdevi = dbus.Interface(bus.get_object('org.freedesktop.Hal', p), 
           "org.freedesktop.Hal.Device") 
     return bdevi.GetAllProperties() 

    bdevs = hal.FindDeviceByCapability("block") 
    for bdev in bdevs: 
     props = getdevprops(bdev) 
     if (props['block.major'], props['block.minor']) == (major, minor): 
      parentprops = getdevprops(props['info.parent']) 
      return (str(props['block.device']), 
        str(parentprops['block.device'])) 

def ask_sysfs(major, minor): 
    from glob import glob 
    needle = "%d:%d" % (major, minor) 

    files = glob("/sys/class/block/*/dev") 
    for f in files: 
     if file(f).read().strip() == needle: 
      return os.path.dirname(f) 

    return None 

if __name__ == '__main__': 
    main() 
1

Recientemente tuve una necesidad de esta solución también. Después de ver todos los métodos intrincados de obtener el resultado que quería a través de Python puro, decidí recurrir al caparazón en busca de ayuda.

import subprocess 
device = subprocess.check_output("grep '/filesystem' /proc/mounts | awk '{printf $1}'", shell=True) 
print device 

Esto me da exactamente lo que quiero, la secuencia del dispositivo donde está montado mi sistema de archivos.

Corto, dulce, y se ejecuta en python. :)

0

Existen problemas con bastantes de las soluciones anteriores. También hay un problema con la pregunta.

La última respuesta (buscar/proc/montajes) simplemente no funciona: la búsqueda de "/" coincidirá con cada línea en/proc/mounts.Incluso la corrección de este como esto no funcionará:

import subprocess 
device = subprocess.check_output("awk '$2 == \"/filesystem\" { print $1}' /proc/mounts", shell=True) 
print device 

Cuando "/ sistema de archivos" es "/" normalmente se obtendrá dos entradas, una para "rootfs" y otro para el dispositivo real. Tampoco funcionará cuando el nombre del sistema de archivos montado tenga espacios (el espacio aparece como \ 040 en/proc/mounts).

El problema se agrava con btrfs subcaudales. Cada subvolumen se monta por separado, pero todos comparten el mismo dispositivo. Si está intentando usar una instantánea btrfs para copias de seguridad (como yo lo hacía), entonces necesita el nombre del subvolumen y una indicación del tipo de sistema de archivos.

Esta función devuelve una tupla de (dispositivo, punto de montaje, sistema de archivos) y parece que funciona:

import os 
def get_filesystem_partition(fs): 
    res = None 
    dev = os.lstat(fs).st_dev 
    for line in file('/proc/mounts'): 
     # lines are device, mountpoint, filesystem, <rest> 
     # later entries override earlier ones 
     line = [s.decode('string_escape') for s in line.split()[:3]] 
     if dev == os.lstat(line[1]).st_dev: 
      res = tuple(line) 
    return res 

que parece funcionar para todos los casos que se me ocurren, aunque espero que todavía son patológicos casos donde cae a pedazos.

0

Cómo sobre el uso de la (Linux) comando (/ sbin/blkid)

$ uname --kernel-name --kernel-release 
Linux 3.2.0-4-amd64 

$ python --version 
Python 2.7.3 

blkid -

#!/usr/bin/env python           

import subprocess 

sys_command = "/sbin/blkid" 
proc = subprocess.Popen(sys_command, 
         stdout=subprocess.PIPE, 
         shell=True) 

# proc.communicate() returns a tuple (stdout,stderr)       
blkid_output = proc.communicate()[0] 

print blkid_output 

Aquí está la salida en un ordenador portátil de doble arranque con una unidad USB (sin montar) (sdb1)

$ ./blkid.py 
/dev/sda1: LABEL="RECOVERY" UUID="xxxx-xxxx" TYPE="vfat" 
/dev/sda2: LABEL="OS" UUID="xxxxxxxxxxxxxxx" TYPE="ntfs" 
/dev/sda5: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="ext4" 
/dev/sda6: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="swap" 
/dev/sda7: UUID="xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx" TYPE="ext4" 
/dev/sdb1: LABEL="CrunchBang" TYPE="iso9660" 
0

Aquí es cómo se puede conseguir simplemente los dispositivos principales y números menores:

import os 
major, minor = divmod(os.stat('/').st_dev, 256) 
Cuestiones relacionadas