文件系统使用量
磁盘空间监控 对于 应对存储短缺故障 以及 前瞻性容量规划 意义重大。
注解
磁盘空间监控这个说法其实不太准确:磁盘 只提供底层块存储,因而只有总容量的概念;至于当前 使用量 、 剩余可用量 等都归 文件系统 管理。因此,正如标题所示,本文采用 文件系统使用量 这个说法。
除了 存储空间 资源,管理员还需要关注 文件节点 资源。对于大部分文件系统, inode 节点数是固定的,也就是说能存储的文件数是固定的。因此,在文件节点耗尽的情况下,就算存储空间还有剩余也无济于事。
指标
文件系统使用量 可以通过 statvfs系统调用 获取,指标涵盖 存储空间 以及 文件节点 :
total_bytes
total_bytes 表示 总存储空间 ,单位为 字节 ,由 statvfs 相关字段计算而来:
[total_bytes = statvfs.f_frsize * statvfs.f_blocks]
statvfs 结构体定义如下:
struct statvfs {
unsigned long f_bsize; /* Filesystem block size */
unsigned long f_frsize; /* Fragment size */
fsblkcnt_t f_blocks; /* Size of fs in f_frsize units */
fsblkcnt_t f_bfree; /* Number of free blocks */
fsblkcnt_t f_bavail; /* Number of free blocks for
unprivileged users */
fsfilcnt_t f_files; /* Number of inodes */
fsfilcnt_t f_ffree; /* Number of free inodes */
fsfilcnt_t f_favail; /* Number of free inodes for
unprivileged users */
unsigned long f_fsid; /* Filesystem ID */
unsigned long f_flag; /* Mount flags */
unsigned long f_namemax; /* Maximum filename length */
};
free_bytes
free_bytes 表示 空闲存储空间 ,单位为 字节 ,同样由 statvfs 相关字段计算而来:
[free_bytes = statvfs.f_frsize * statvfs.f_bfree]
available_bytes
available_bytes 表示 可用存储空间 ,单位为 字节 ,同样由 statvfs 相关字段计算而来:
[available_bytes = statvfs.f_frsize * statvfs.f_bavail]
注解
文件系统通常为 root 用户预留一部分空间,其他非特权用户不能使用。对 root 用户,可用空间是 free_bytes ;对非特权用户,可用空间是 available_bytes 。一般而言, free_bytes 比 available_bytes 大:
[free_bytes > available_bytes]
used_bytes
used_bytes 表示 已用存储空间 ,即总存储空间减去空闲存储空间:
[used_bytes = total_bytes - free_bytes]
used_bytes_percent
used_bytes_percent 表示 可用存储空间百分比 ,计算公式如下:
[used_bytes_percent = \frac{used_bytes}{used_bytes + available_bytes} \times 100\%]
读者可能觉得奇怪,为什么不是除以 total_bytes 呢?——因为对于非特权用户,可用存储空间是 available_bytes 而不是 free_bytes 。对非特权用户来说,总存储空间是:
[total_bytes_for_nonroot = used_bytes + available_bytes]
因此,已用存储空间百分比是针对非特权用户计算的, df 命令也是采用这个口径。
文件节点系列
文件节点 系列指标与 存储空间 系列类似,不再赘述。计算公式列举如下:
[total_files = statvfs.f_files]
[free_files = statvfs.f_ffree]
[available_files = statvfs.f_favail]
[used_files = total_files - free_files]
[used_files_percent = \frac{used_files}{used_files + available_files} \times 100\%]
采集
借助 statvfs系统调用 ,采集某个文件系统使用量统计毫无难度。
可问题是,如何获取所有已挂载的文件系统呢?——答案是 proc 伪文件系统,内核将所有文件系统挂载点暴露在 /proc/mounts 文件中。
这是一个简单的示例程序,依次展示每个文件系统使用量统计:
import os
from tabulate import (
tabulate,
)
TABLE_HEADER = (
'mount_point',
'total_bytes',
'used_bytes',
'used_bytes_percent',
'total_files',
'used_files',
'used_files_percent',
)
def get_mount_points():
with open('/proc/mounts') as f:
return [
line.strip().split()
for line in f
]
def get_fs_usage():
devices = set()
table_data = []
for device, mount_point, _, _, _, _ in get_mount_points():
# skip non-device
if not device.startswith('/dev'):
continue
if device in devices:
continue
devices.add(device)
# call statvfs to fetch file system statistics
statvfs = os.statvfs(mount_point)
f_frsize = statvfs.f_frsize
# calculate space
total_bytes = statvfs.f_blocks * f_frsize
free_bytes = statvfs.f_bfree * f_frsize
available_bytes = statvfs.f_bavail * f_frsize
used_bytes = total_bytes - free_bytes
used_bytes_percent = 100. * used_bytes / (used_bytes + available_bytes)
# calculate files
total_files = statvfs.f_files
free_files = statvfs.f_ffree
available_files = statvfs.f_favail
used_files = total_files - free_files
used_files_percent = 100. * used_files / (used_files + available_files)
table_data.append((
mount_point,
total_bytes,
used_bytes,
used_bytes_percent,
total_files,
used_files,
used_files_percent,
))
print(tabulate(table_data, TABLE_HEADER, floatfmt='6.2f'))
print()
if __name__ == '__main__':
get_fs_usage()
get_mount_points 函数读取 /proc/mounts 文件,从中切分出挂载点并返回。
get_fs_usage 函数遍历每个文件系统挂载点,调用 statvfs 获取并计算使用量统计:
- 第 30 行,循环遍历每个文件系统挂载点;
- 第 31 行,跳过一些非设备文件系统,如 procfs 伪文件系统;
- 第 35-38 行配合,跳过重复挂载点;
- 第 41 行,调用 statvfs 系统调用,获取文件系统统计值;
- 第 46-59 行,根据上节相关公式计算所有指标;
下一步
订阅更新,获取更多学习资料,请关注我们的 微信公众号 :