Déterminer le périphérique du système de fichiers en Python

Comment utilisez-vous Python pour déterminer quel périphérique / partition Linux contient un système de fichiers donné?

par exemple

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

Ce n’est pas le plus pur, mais cela va vous permettre de démarrer:

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

Sous OS X:

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

Sur Ubuntu:

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

Pour obtenir le nom du périphérique, supprimez le numéro mineur du nom de la partition. Sous OS X, coupez également le numéro minuscule.

Votre question concernait Linux, donc c’est (plus ou moins) spécifique à Linux.

Vous trouverez ci-dessous un exemple de code pour trois variantes permettant de mapper major / minor sur un nom de périphérique.

  • Analyser / proc / partitions.
  • Demandez à Hal. Hal garde également une trace du périphérique “parent”, ce qui signifie que vous pouvez facilement obtenir le disque aussi bien que la partition.
  • Vérifiez sysfs vous-même. C’est là que hal tire ses informations.

Je dirais que / proc / partitions est le plus simple – ce n’est qu’un fichier à ouvrir et à vérifier. hal vous donne le plus d’informations et élimine beaucoup de détails. sysfs peut être considéré comme plus correct que / proc / partitions et ne nécessite pas que hal soit en cours d’exécution.

Pour un programme de bureau, je choisirais hal. Sur un système embarqué, j’irais avec 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().ssortingp() == needle: return os.path.dirname(f) return None if __name__ == '__main__': main() 

Il semble que cet article /dev/sda2 partie de votre réponse (toujours pas sûr de savoir comment extraire le majeur / mineur de l’entrée /dev/sda2 pour le faire correspondre avec ce que os.stat() renvoie pour / :

Numéro de périphérique dans la sortie de la commande stat

 >>> import os >>> print hex(os.stat('/')[2]) 0x802 \ \minor device number \major device number [me@server /]$ ls -l /dev/sda2 brw-rw---- 1 root disk 8, 2 Jun 24 2004 /dev/sda2 [me@server jgaines2]$ \ \minor device number \major device number 

J’ai récemment eu besoin de cette solution. Après avoir vu toutes les méthodes compliquées pour obtenir le résultat que je voulais grâce au python pur, j’ai décidé de me tourner vers le shell pour obtenir de l’aide.

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

Cela me donne exactement ce que je veux, la chaîne de périphérique où mon système de fichiers est monté.

Court, doux et fonctionne en python. 🙂

Il existe des problèmes avec plusieurs des solutions ci-dessus. Il y a aussi un problème avec la question.

La dernière réponse (chercher / proc / mounts) ne fonctionne tout simplement pas: la recherche de “/” correspondra à chaque ligne de / proc / mounts. Même en corrigeant cela comme cela ne fonctionnera pas:

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

Lorsque “/ filesystem” est “/”, vous obtiendrez généralement deux entrées, une pour “rootfs” et une pour le périphérique réel. Cela ne fonctionnera pas non plus lorsque le nom du système de fichiers monté comporte des espaces (l’espace apparaît sous la forme \ 040 dans / proc / mounts).

Le problème est aggravé par les sous-volumes de btrfs. Chaque sous-volume est monté séparément, mais tous partagent le même périphérique. Si vous essayez d’utiliser un instantané de btrfs pour les sauvegardes (comme je l’étais), vous avez besoin du nom du sous-volume et d’une indication du type de système de fichiers.

Cette fonction retourne un tuple de (périphérique, sharepoint assembly, système de fichiers) et semble fonctionner:

 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,  # later ensortinges override earlier ones line = [s.decode('ssortingng_escape') for s in line.split()[:3]] if dev == os.lstat(line[1]).st_dev: res = tuple(line) return res 

Cela semble fonctionner pour tous les cas que je peux imaginer, même si je pense qu’il ya encore des cas pathologiques qui s’écroulent.

Comment utiliser la commande blkid (linux) (/ sbin / blkid)

 $ uname --kernel-name --kernel-release Linux 3.2.0-4-amd64 $ python --version Python 2.7.3 

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

Voici la sortie sur un ordinateur portable à double démarrage avec un lecteur USB (non monté) (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" 

Voici comment vous pouvez simplement obtenir les numéros majeurs et mineurs des périphériques:

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