同类问题我见过几次,现场表现一样但根因不同,所以第一步是把范围缩小。 阿里云 ecs.g7 上跑 CentOS 7.9,df -h 显示根分区四十 G 已经用满,可 du -sh 把各目录加起来只有二十一 G,差的十九 G 找不到落点,重启 php-fpm 之后才回落。

先把影响面控制住,再谈彻底修复,顺序反了容易在高峰期出二次故障。

先分清是哪一类原因

  1. 进程还持有被 rm 掉的文件句柄,空间要等进程退出或者重新打开文件才会释放
  2. 日志删掉了但 nginx 和 php-fpm 的文件描述符仍指向原 inode,一直在往里追加内容
  3. 某个数据目录被后挂的云盘覆盖住,写入其实全都落在了根分区上

按顺序处理

1. 先列出已删除却仍占空间的文件句柄

lsof +L1 | awk '{print $1,$2,$7,$9}' | tail -20

2. 重启持有句柄的服务,让内核回收空间

systemctl restart php-fpm nginx

3. 确认数据目录没有被后挂的盘遮住

findmnt -T /www/wwwroot && df -h /www/wwwroot

4. 核对回收结果和剩下的差额

df -h / && du -xsh /* 2>/dev/null | sort -h | tail

怎么确认已经恢复

df -h 中根分区已用降到二十一 G 左右,lsof +L1 输出为空,du 与 df 的差值回到一 G 以内并且写入正常。

容易忽略的地方

不要用 rm 删正在写的日志,logrotate 配 copytruncate 或者让应用自己 reopen 才会立刻归还空间;重启前先把 lsof 输出留存一份,便于回溯是哪天埋下的问题。 命令执行完不要只看有没有报错,还要看输出里的计数和状态码是否符合预期。

作者 9823189