“服务突然写不进日志”最常见的根因就是磁盘。排查顺序要固定,否则会很浪费时间。
第一步:分清是空间还是 inode
df -h # 空间(人类可读)
df -i # inode 数量
两种病表现一样(都写不进去),处方不同:
| 现象 | 病因 | 典型来源 |
|---|---|---|
df -h 满,df -i 正常 |
空间用尽 | 日志、备份、数据库 |
df -h 空,df -i 满 |
inode 用尽 | 海量小文件(缓存、session 文件、邮件队列) |
第二步:找出占空间的大头
du -h --max-depth=1 /home | sort -h # 逐层下钻
du -ah /var | sort -h | tail -20 # 单文件前 20
注意“文件已删除但空间没释放”:进程还持有句柄时 du 看不见、df 却已占用。
lsof +L1 # 列出已删除但仍被占用的文件
# 处置:重启持有它的进程,或用 `> /proc/<pid>/fd/<n>` 截断
第三步:IO 高时先定位“谁”
iostat -x 1 5 # 看 %util 与 await:接近 100% 就是打满了
iotop -o # 按进程看实时读写(需要 root)
pidstat -d 1 5 # 按进程看读写速率
%util 高且 await 大 → 磁盘确实到瓶颈;反之如果 %util 很低却慢,问题通常在别处(网络、锁、GC)。
日常维护
journalctl --disk-usage # systemd 日志占了多少
sudo journalctl --vacuum-size=200M # 按体积回收
sudo journalctl --vacuum-time=30d # 按时间回收
数据库的 WAL、容器镜像层、node_modules、pnpm store 都容易悄悄涨到几个 G,建议纳入例行检查。
一个小脚本:一行看清关键指标
echo "== 空间 =="; df -h | grep -v tmpfs
echo "== inode =="; df -i | grep -v tmpfs
echo "== 已删除未释放 =="; lsof +L1 2>/dev/null | head
echo "== 日志占用 =="; journalctl --disk-usage
经验:先看
df,再看du,最后看lsof +L1。顺序反了会在“文件到底在哪”上浪费很多时间。
