Определить устройство файловой системы в Python - PullRequest
5 голосов
/ 11 октября 2011

Как вы используете Python, чтобы определить, какое устройство / раздел Linux содержит данную файловую систему?

например,

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

Ответы [ 7 ]

2 голосов
/ 11 октября 2011

Ваш вопрос касался Linux, так что это (более или менее) специфично для Linux.

Ниже приведен пример кода для трех вариантов сопоставления основного / вспомогательного имени с именем устройства.

  • Parse /proc/partitions.
  • Ask hal.Хэл также отслеживает «родительское» устройство, то есть вы можете легко получить диск, а также раздел.
  • Проверьте sysfs самостоятельно.Вот откуда hal получает информацию.

Я бы сказал, что / proc / partitions - самый простой - это всего лишь один файл, который нужно открыть и проверить.Хэл дает вам большую информацию, и абстрагирует много деталей.sysfs может рассматриваться как более правильный, чем / proc / partitions, и для него не требуется запускать hal.

Для настольной программы я бы выбрал hal.На встроенной системе я бы пошел с 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 голос
/ 08 июня 2013

У меня недавно тоже была потребность в этом решении. Увидев все запутанные методы получения нужного мне результата через чистый питон, я решил обратиться за помощью к оболочке.

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

Это дает мне именно то, что я хочу, строку устройства, где смонтирована моя файловая система.

Короткий, сладкий и работает на питоне. :)

1 голос
/ 11 октября 2011

Похоже, что в этом посте есть какой-то ваш ответ (до сих пор не уверены, как извлечь основной / вспомогательный элемент из записи /dev/sda2, чтобы сопоставить его с тем, что os.stat() возвращает для /:

Номер устройства в выводе команды 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
0 голосов
/ 08 февраля 2018

Вот как вы можете просто получить старшие и младшие номера устройств:

import os
major, minor = divmod(os.stat('/').st_dev, 256)
0 голосов
/ 26 февраля 2015

Как насчет использования команды (linux) blkid (/ 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

Вот вывод на ноутбуке с двойной загрузкой с (не подключенным) USB-накопителем (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 голосов
/ 25 сентября 2013

Есть проблемы с некоторыми из вышеперечисленных решений. На самом деле есть проблема и с вопросом.

Последний ответ (поиск / proc / mounts) просто не работает: поиск "/" будет соответствовать каждой строке в / proc / mounts. Даже исправить это так не получится:

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

Когда "/ filesystem" равен "/", вы обычно получаете две записи, одну для "rootfs" и одну для реального устройства. Это также не будет работать, если в имени смонтированной файловой системы есть пробелы (пробел отображается как \ 040 в /proc/mounts).

Проблема усугубляется с помощью томов btrfs. Каждый подобъем монтируется отдельно, но все они используют одно и то же устройство. Если вы пытаетесь использовать снимок btrfs для создания резервных копий (как я), тогда вам нужно имя подобъема и указание типа файловой системы.

Эта функция возвращает кортеж (устройство, точка монтирования, файловая система) и, похоже, работает:

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

Кажется, это работает для всех случаев, о которых я могу подумать, хотя я ожидаю, что все еще есть патологические случаи, когда он падает на куски.

0 голосов
/ 11 октября 2011

Это не самый чистый, но это поможет вам начать:

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

В OS X:

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

В Ubuntu:

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

Чтобы получить имя устройства, отрежьте младший номер от имени раздела.На OS X также нарезать 's' + младший номер.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...