如何计算磁盘使用率以匹配df命令的Use%输出?
Rust计算磁盘使用率与df命令结果不一致的解决思路
你遇到的问题核心是statvfs字段含义的理解偏差以及df命令的计算逻辑和你代码里的逻辑不一致,下面拆解原因并给出修正方案:
问题根源解析
已用空间计算错误:
你代码里用total_space - blocks_available()得到的"已用空间",其实是已用空间+root用户预留的空间。因为statvfs的blocks_available()返回的是普通用户可使用的空闲块数,而blocks_free()才是文件系统的总空闲块数(包含root预留的不可被普通用户访问的空间)。df命令的Used字段正是用Total - Free(Free对应blocks_free())计算出来的。使用率计算逻辑不一致:
df的Use%并不是简单的Used/Total*100,而是Used/(Used+Available)*100——这里的Available是普通用户可用空间(对应blocks_available()),分母是实际可分配的空间总和(已用+普通用户可用),排除了root预留的那部分不可用空间。
看你的示例数据就能验证:
- 总空间:6779424768
- df的Used:2713636864 = 总空间 - 总空闲空间(6779424768 - 4065787904)
- 你代码里的Used:3081613312 = 总空间 - 普通用户可用空间(6779424768 - 3697811456)
- 两者的差值正好是root预留的空间:3081613312 - 2713636864 = 367976448
修正后的代码
use nix::sys::statvfs::statvfs; macro_rules! cast { ($x:expr) => { u64::from($x) }; } fn main() { let stat = statvfs("/var/db".as_bytes()).unwrap(); // 总空间:和df的1B-blocks完全一致 let total_space = cast!(stat.block_size()) * cast!(stat.blocks()); // 总空闲空间(包含root预留):对应df里的Total - Used let free_space = cast!(stat.block_size()) * cast!(stat.blocks_free()); // df的Used字段:总空间 - 总空闲空间 let used_space = total_space - free_space; // df的Available字段:普通用户可使用的空闲空间 let avail_space = cast!(stat.block_size()) * cast!(stat.blocks_available()); // 对齐df的使用率计算逻辑:Used / (Used + Available) * 100 let usage = used_space * 100 / (used_space + avail_space); println!("total: {}", total_space); println!("avail: {}", avail_space); println!("used: {}", used_space); println!("use%: {}%", usage); }
关键字段说明
再明确下statvfs几个核心字段的含义,避免再踩坑:
blocks():文件系统的总块数blocks_free():文件系统的总空闲块数(包含root用户专属的预留块)blocks_available():普通用户可访问的空闲块数(排除root预留)block_size():文件系统的基础块大小,用来将块数转换为字节数
运行修正后的代码,你会得到和df命令完全一致的结果啦。
内容的提问来源于stack exchange,提问作者nbari
相关产品推荐
相关产品推荐

