监控盘满了以后,采集程序照常打日志说写入成功,重启一看当天的文件全是 0 字节。df 显示 Use% 100,程序自己的错误计数还是 0。乍看像缓存或者权限的锅,追下去往往不是。
f.write(payload) f.flush() os.fsync(f.fileno()) # 另起线程定期 df -h /data 采样
追下去是这么回事:write 只是把数据拷进页缓存,真正落盘由内核回写,空间不足的错误要等到回写时才产生。程序没调 fsync 也没检查 close 的返回值,就看到了一次成功的系统调用。
「磁盘满写入静默失败」相关的验证我通常做两遍,改完一次、隔天再看一次,确认不是临时生效。测试环境和线上的差别,往往就在版本号和那几行被忽略的配置上。
线上出问题先对时间点,跟发布、备份、任务执行的时刻排一排,能省掉一半功夫。
具体做法是,写完关键文件调 os.fsync(f.fileno()) 让错误当场暴露;检查 close 的返回值 不要只 catch write;起一个线程盯 df 的可用空间 低于阈值就停写;日志库换成会抛异常的 handler 别吞掉 IOError。
验收就看一点,把测试分区写满后程序立刻报 OSError 28 不再出现 0 字节的当天文件。
