简体   繁体   English

在Python中确定文件系统的设备

[英]Determine Device of Filesystem in Python

How do you use Python to determine which Linux device/partition contains a given filesystem? 如何使用Python来确定哪个Linux设备/分区包含给定的文件系统?

eg 例如

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

Your question was about Linux, so this is (more or less) linux specific. 你的问题是关于Linux的,所以这是(或多或少)linux特有的。

Below is code example for three variants for mapping major/minor to a device name. 下面是将主要/次要映射到设备名称的三种变体的代码示例。

  • Parse /proc/partitions. 解析/ proc /分区。
  • Ask hal. 问哈。 Hal also keeps track of "parent" device, meaning you can easily get the disk aswell as the partition. Hal还跟踪“父”设备,这意味着您可以轻松获取磁盘以及分区。
  • Check sysfs yourself. 自己检查sysfs。 This is where hal gets its information from. 这是hal从中获取信息的地方。

I'd say that /proc/partitions is simplest - it is just one file to open and check. 我会说/ proc / partitions是最简单的 - 它只是一个要打开和检查的文件。 hal gives you most information, and abstracts away lots of details. hal为您提供大部分信息,并抽象出大量细节。 sysfs may be viewed as more correct that /proc/partitions and doesn't require hal to be running. sysfs可能被视为/ proc / partitions更正确,并且不需要hal运行。

For a desktop program I would go for hal. 对于桌面程序,我会去做。 On an embedded system I'd go with sysfs. 在嵌入式系统上,我会使用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()

I recently had a need for this solution also. 我最近也需要这个解决方案。 After seeing all the convoluted methods of getting the result I wanted through pure python, I decided to turn to the shell for help. 在看到所有通过纯python获得结果的复杂方法之后,我决定转向shell寻求帮助。

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

This gives me exactly what I want, the device string for where my filesystem is mounted. 这给了我我想要的,我的文件系统安装位置的设备字符串。

Short, sweet, and runs in python. 简短,甜蜜,并在python中运行。 :) :)

There are problems with quite a few of the above solutions. 上述解决方案存在很多问题。 There's actually a problem with the question as well. 这个问题实际上也存在问题。

The last answer (searching /proc/mounts) just doesn't work: searching for "/" will match every line in /proc/mounts. 最后一个答案(搜索/ proc / mounts)不起作用:搜索“/”将匹配/ proc / mounts中的每一行。 Even correcting this like this won't work: 即使像这样纠正这个也行不通:

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

When "/filesystem" is "/" you'll typically get two entries, one for "rootfs" and one for the actual device. 当“/ filesystem”为“/”时,您通常会得到两个条目,一个用于“rootfs”,一个用于实际设备。 It also won't work when the mounted file system name has spaces in it (the space appears as \\040 in /proc/mounts). 当挂载的文件系统名称中包含空格时,它也不起作用(空格在/ proc / mounts中显示为\\ 040)。

The problem is made worse with btrfs subvolumes. btrfs子卷使问题变得更糟。 Each subvolume is mounted separately but they all share the same device. 每个子卷都是单独安装的,但它们都共享同一个设备。 If you're trying to use a btrfs snapshot for backups (as I was) then you need the subvolume name and an indication of the filesystem type. 如果您尝试使用btrfs快照进行备份(就像我一样),那么您需要子卷名称和文件系统类型的指示。

This function returns a tuple of (device, mountpoint, filesystem) and seems to work: 此函数返回(设备,挂载点,文件系统)的元组,似乎工作:

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

That seems to work for all the cases I can think of, although I expect that there are still pathological cases where it falls to bits. 这似乎适用于我能想到的所有情况,尽管我认为仍然存在病态的情况,它会落到位。

It looks like this post has some of your answer (still not sure just how to grab the major/minor out of the /dev/sda2 entry to match it up with what os.stat() returns for / : 看起来这个帖子有你的一些答案(仍然不确定如何从/dev/sda2条目中获取主要/次要以匹配os.stat()/返回的内容:

Device number in stat command output 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

How about using the (linux) blkid command (/sbin/blkid) 如何使用(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

Here's the output on a dual-boot laptop with an (unmounted) USB drive (sdb1) 这是带有(未安装)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"

Here is how you can simply get the devices major and minor numbers: 以下是如何简单地获取设备的主要和次要数字:

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

It is not the purdiest, but this will get you started: 它不是最卑鄙的,但这会让你开始:

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

On OS X: 在OS X上:

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

On Ubuntu: 在Ubuntu上:

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

To get the device name, chop off the minor number from the partition name. 要获取设备名称,请从分区名称中删除次要编号。 On OS X, also chop the 's' + minor number. 在OS X上,也要删除's'+次要号码。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM