如何在 Linux 上获取磁盘使用情况图?

如何在 Linux 上获取磁盘使用情况图?

我想创建一个映射,以显示哪些文件写入硬盘驱动器的哪个位置。它应该输出类似目录树的内容,并且对于每个文件,输出组成整个文件的扇区列表 ([10-20],[80-90],[60-70])。例如,创建类似老式 Windows 磁盘碎片整理程序的可视化效果:

Windows 碎片整理

有没有什么工具可以实现这个功能?

答案1

Debian 派生的标准工具是Disk Usage Analyser( baobab),但是它不会显示碎片。

我知道显示碎片的唯一方法是逐个文件地使用命令行进程,使用中描述的工具之一这个答案

为此,我编写了一个脚本hdparm --fibmap:-

#!/bin/bash
#
# frags MountPoint SkipFrags    Reports all files under MountPoint with more than SkipFrags fragments
#       MountPoint defaults to / (root file system)
#       SkipFrags  defaults to 1 (report all files with more than one fragment)
#                  (setting to 0 will report all files, including unfragmanted)
#
# The report is sorted in fragment count order and must be run as root 
#
[ "${1:0:1}" == "-" ] && \
    echo 'frags MountPoint SkipFrags    Reports all files under MountPoint with more than SkipFrags fragments' && \
    echo '      MountPoint defaults to / (root file system)' && \
    echo '      SkipFrags  defaults to 1 (report all files with more than one fragment)' && \
    echo '                 (setting to 0 will report all files, including unfragmanted)' && \
    echo 'The report is sorted in fragment count order and must be run as root' && \
    { return 1 2>/dev/null; exit 1; }
[ "$(whoami)" != "root" ] && { echo 'Must be run from "root"' >&2; return 13 2>/dev/null; exit 13; }
eof='***EOF***'    ; # End-of-file marker
{ find "$1"/ -mount -type f; echo "$eof"; } | \
    while read -r f; \
        do  [ "$f" == "$eof" ] && { echo -ne "\e[K" >&2; continue; }; \
            r=$(hdparm --fibmap "$f" | grep -E "^[ 0-9]+$" | wc -l); \
            [ $r -gt "${2:-1}" ] && { echo -ne "\e[K--- $r: ${f::$(($COLUMNS-${#r}-6))}\r" >&2; echo "$r: $f"; } \
        done | \
sort -nt :

请注意,虽然我已将脚本记录为从其安装点扫描整个磁盘,但您可以获得特定目录的排序结果,并且我建议首先在小目录上执行此操作,以确保它给出合理的结果。

这个过程相当慢,而且排序意味着在扫描完每个文件之前你不会得到任何结果,所以我在stderr找到每个要报告的文件时添加了一个诊断。转义序列是 forxterm并且依赖于由in (或另一个初始化文件)$COLUMNS设置。避免换行可以防止脚本因滚动而变慢。shopt -s checkwinsize; export COLUMNS~/.bashrc

我使用了[ ... ] &&而不是if [ ... ]; then来减少嵌套并缩短脚本。该return 1 2>/dev/null; exit 1;序列是我学到的一个技巧,无论脚本是正常调用还是通过./source命令调用,它都会返回错误代码。

答案2

我通常用 Python 编写脚本,所以如果有人对 AFH 答案的 Python 版本感兴趣。我的方法取决于命令filefrag。这将从 cli 参数开始遍历目录树root,并收集文件名、文件大小和块范围。如果需要,添加参数来指定块大小等可能会很方便。

import subprocess
import os
import re
import argparse

size = re.compile("(\d+) \(\d+ block")

def get_extents(root):
    for root, dirs, files in os.walk(root):
        for f in files:
            fullpath = os.path.abspath(os.path.join(root, f))
            output = subprocess.check_output(["filefrag", "-e", "-v", fullpath]).decode("utf-8")
            lines = output.splitlines()
            sizeline = lines[1]
            extentlines = lines[3:-1]
            print(fullpath)
            print("size in bytes:", size.search(sizeline).group(1))
            extents = []
            for extentline in extentlines:
                stuff = extentline.split()
                lower = stuff[3].strip(".")
                upper = stuff[4].strip(":")
                extents.append((lower, upper))
            print("extents:", extents)

if __name__ == "__main__":
    parser = argparse.ArgumentParser("get the extents of all the files")
    parser.add_argument("root", type=os.path.expanduser, help="the root folder to examine recursively on")

    args = parser.parse_args()
    get_extents(args.root)

相关内容