it-swarm.com.de

Finden Sie die Größe und den freien Speicherplatz des Dateisystems, das eine bestimmte Datei enthält

Ich verwende Python 2.6 unter Linux. Was ist der schnellste Weg:

  • um festzustellen, welche Partition ein bestimmtes Verzeichnis oder eine bestimmte Datei enthält?

    Angenommen, /dev/sda2 ist montiert auf /home, und /dev/mapper/foo ist montiert auf /home/foo. Aus der Zeichenfolge "/home/foo/bar/baz" Ich möchte das Paar wiederherstellen ("/dev/mapper/foo", "home/foo").

  • und dann, um Nutzungsstatistiken der angegebenen Partition zu erhalten? Zum Beispiel gegeben /dev/mapper/foo Ich möchte die Größe der Partition und den verfügbaren freien Speicherplatz (entweder in Bytes oder ungefähr in Megabytes) erhalten.

67

Wenn Sie nur den freien Speicherplatz auf einem Gerät benötigen, lesen Sie die Antwort mit os.statvfs() weiter unten.

Wenn Sie auch den Gerätenamen und den Bereitstellungspunkt benötigen, die der Datei zugeordnet sind, sollten Sie ein externes Programm aufrufen, um diese Informationen abzurufen. df liefert alle Informationen, die Sie benötigen - wenn es als df filename aufgerufen wird, wird eine Zeile über die Partition gedruckt, die die Datei enthält.

Um ein Beispiel zu geben:

import subprocess
df = subprocess.Popen(["df", "filename"], stdout=subprocess.PIPE)
output = df.communicate()[0]
device, size, used, available, percent, mountpoint = \
    output.split("\n")[1].split()

Beachten Sie, dass dies ziemlich spröde ist, da es vom genauen Format der Ausgabe von df abhängt, mir ist jedoch keine robustere Lösung bekannt. (Es gibt einige Lösungen, die auf dem Dateisystem /proc Basieren und noch weniger portabel sind als dieses.)

43
Sven Marnach

Dies gibt nicht den Namen der Partition an, aber Sie können die Dateisystemstatistik direkt mit dem Unix-Systemaufruf statvfs abrufen. Um es von Python aus aufzurufen, verwenden Sie os.statvfs('/home/foo/bar/baz') .

Die relevanten Felder im Ergebnis, nach POSIX :

unsigned long f_frsize   Fundamental file system block size. 
fsblkcnt_t    f_blocks   Total number of blocks on file system in units of f_frsize. 
fsblkcnt_t    f_bfree    Total number of free blocks. 
fsblkcnt_t    f_bavail   Number of free blocks available to 
                         non-privileged process.

Um die Werte zu verstehen, multiplizieren Sie mit f_frsize:

import os
statvfs = os.statvfs('/home/foo/bar/baz')

statvfs.f_frsize * statvfs.f_blocks     # Size of filesystem in bytes
statvfs.f_frsize * statvfs.f_bfree      # Actual number of free bytes
statvfs.f_frsize * statvfs.f_bavail     # Number of free bytes that ordinary users
                                        # are allowed to use (excl. reserved space)
114
import os

def get_mount_point(pathname):
    "Get the mount point of the filesystem containing pathname"
    pathname= os.path.normcase(os.path.realpath(pathname))
    parent_device= path_device= os.stat(pathname).st_dev
    while parent_device == path_device:
        mount_point= pathname
        pathname= os.path.dirname(pathname)
        if pathname == mount_point: break
        parent_device= os.stat(pathname).st_dev
    return mount_point

def get_mounted_device(pathname):
    "Get the device mounted at pathname"
    # uses "/proc/mounts"
    pathname= os.path.normcase(pathname) # might be unnecessary here
    try:
        with open("/proc/mounts", "r") as ifp:
            for line in ifp:
                fields= line.rstrip('\n').split()
                # note that line above assumes that
                # no mount points contain whitespace
                if fields[1] == pathname:
                    return fields[0]
    except EnvironmentError:
        pass
    return None # explicit

def get_fs_freespace(pathname):
    "Get the free space of the filesystem containing pathname"
    stat= os.statvfs(pathname)
    # use f_bfree for superuser, or f_bavail if filesystem
    # has reserved space for superuser
    return stat.f_bfree*stat.f_bsize

Einige Beispielpfadnamen auf meinem Computer:

path 'trash':
  mp /home /dev/sda4
  free 6413754368
path 'smov':
  mp /mnt/S /dev/sde
  free 86761562112
path '/usr/local/lib':
  mp / rootfs
  free 2184364032
path '/proc/self/cmdline':
  mp /proc proc
  free 0

PS

wenn auf Python ≥3.3, gibt es shutil.disk_usage(path), das ein benanntes Tupel von (total, used, free) in Bytes zurückgibt.

22
tzot

Ab Python 3.3 gibt es eine einfache und direkte Möglichkeit, dies mit der Standardbibliothek zu tun:

$ cat free_space.py 
#!/usr/bin/env python3

import shutil

total, used, free = shutil.disk_usage(__file__)
print(total, used, free)

$ ./free_space.py 
1007870246912 460794834944 495854989312

Diese Zahlen sind in Bytes angegeben. Siehe die Dokumentation für weitere Informationen.

16
Xiong Chiamiov

Dies sollte alles machen, was Sie gefragt haben:

import os
from collections import namedtuple

disk_ntuple = namedtuple('partition',  'device mountpoint fstype')
usage_ntuple = namedtuple('usage',  'total used free percent')

def disk_partitions(all=False):
    """Return all mountd partitions as a nameduple.
    If all == False return phyisical partitions only.
    """
    phydevs = []
    f = open("/proc/filesystems", "r")
    for line in f:
        if not line.startswith("nodev"):
            phydevs.append(line.strip())

    retlist = []
    f = open('/etc/mtab', "r")
    for line in f:
        if not all and line.startswith('none'):
            continue
        fields = line.split()
        device = fields[0]
        mountpoint = fields[1]
        fstype = fields[2]
        if not all and fstype not in phydevs:
            continue
        if device == 'none':
            device = ''
        ntuple = disk_ntuple(device, mountpoint, fstype)
        retlist.append(ntuple)
    return retlist

def disk_usage(path):
    """Return disk usage associated with path."""
    st = os.statvfs(path)
    free = (st.f_bavail * st.f_frsize)
    total = (st.f_blocks * st.f_frsize)
    used = (st.f_blocks - st.f_bfree) * st.f_frsize
    try:
        percent = ret = (float(used) / total) * 100
    except ZeroDivisionError:
        percent = 0
    # NB: the percentage is -5% than what shown by df due to
    # reserved blocks that we are currently not considering:
    # http://goo.gl/sWGbH
    return usage_ntuple(total, used, free, round(percent, 1))


if __== '__main__':
    for part in disk_partitions():
        print part
        print "    %s\n" % str(disk_usage(part.mountpoint))

Auf meiner Box steht der obige Code:

[email protected]:~/dev$ python foo.py 
partition(device='/dev/sda3', mountpoint='/', fstype='ext4')
    usage(total=21378641920, used=4886749184, free=15405903872, percent=22.9)

partition(device='/dev/sda7', mountpoint='/home', fstype='ext4')
    usage(total=30227386368, used=12137168896, free=16554737664, percent=40.2)

partition(device='/dev/sdb1', mountpoint='/media/1CA0-065B', fstype='vfat')
    usage(total=7952400384, used=32768, free=7952367616, percent=0.0)

partition(device='/dev/sr0', mountpoint='/media/WB2PFRE_IT', fstype='iso9660')
    usage(total=695730176, used=695730176, free=0, percent=100.0)

partition(device='/dev/sda6', mountpoint='/media/Dati', fstype='fuseblk')
    usage(total=914217758720, used=614345637888, free=299872120832, percent=67.2)
13

Der einfachste Weg, es herauszufinden.

import os
from collections import namedtuple

DiskUsage = namedtuple('DiskUsage', 'total used free')

def disk_usage(path):
    """Return disk usage statistics about the given path.

    Will return the namedtuple with attributes: 'total', 'used' and 'free',
    which are the amount of total, used and free space, in bytes.
    """
    st = os.statvfs(path)
    free = st.f_bavail * st.f_frsize
    total = st.f_blocks * st.f_frsize
    used = (st.f_blocks - st.f_bfree) * st.f_frsize
    return DiskUsage(total, used, free)
8
mosquito

Für den ersten Punkt können Sie versuchen, os.path.realpath Um einen kanonischen Pfad zu erhalten, überprüfen Sie ihn mit /etc/mtab (Eigentlich würde ich vorschlagen, getmntent aufzurufen, aber ich finde keinen normalen Weg, um darauf zuzugreifen), um die längste Übereinstimmung zu finden. (Um sicherzugehen, sollten Sie wahrscheinlich sowohl die Datei als auch den vermuteten Einhängepunkt stat, um zu überprüfen, ob sie sich tatsächlich auf demselben Gerät befinden.)

Verwenden Sie für den zweiten Punkt os.statvfs um Informationen zur Blockgröße und -nutzung zu erhalten.

(Haftungsausschluss: Ich habe nichts davon getestet. Das meiste, was ich weiß, stammt aus den coreutils-Quellen.)

6
Hasturkun

Für den zweiten Teil Ihrer Frage, "Nutzungsstatistik der angegebenen Partition abrufen", macht psutil dies mit der Funktion disk_usage (path) einfach. Wenn ein Pfad angegeben wird, gibt disk_usage() ein benanntes Tupel zurück, das die Summe, den belegten und den freien Speicherplatz in Bytes zuzüglich der prozentualen Auslastung enthält.

Einfaches Beispiel aus der Dokumentation:

>>> import psutil
>>> psutil.disk_usage('/')
sdiskusage(total=21378641920, used=4809781248, free=15482871808, percent=22.5)

Psutil funktioniert unter anderem mit Python Versionen von 2.6 bis 3.6 und unter Linux, Windows und OSX.

4
andrew
import os

def disk_stat(path):
    disk = os.statvfs(path)
    percent = (disk.f_blocks - disk.f_bfree) * 100 / (disk.f_blocks -disk.f_bfree + disk.f_bavail) + 1
    return percent


print disk_stat('/')
print disk_stat('/data')
3
LawrenceLi

Normalerweise ist der /proc Verzeichnis enthält solche Informationen in Linux, es ist ein virtuelles Dateisystem. Beispielsweise, /proc/mounts gibt Auskunft über aktuell gemountete Festplatten; und Sie können es direkt analysieren. Dienstprogramme wie top, df verwenden alle /proc.

Ich habe es nicht benutzt, aber das könnte auch helfen, wenn Sie einen Wrapper wollen: http://bitbucket.org/chrismiles/psi/wiki/Home

1
ustun