“服务突然写不进日志”最常见的根因就是磁盘。排查顺序要固定,否则会很浪费时间。

第一步:分清是空间还是 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。顺序反了会在“文件到底在哪”上浪费很多时间。