当前位置: 首页 > news >正文

Ubuntu 根分区 inode 被打满的排查过程

Ubuntu 根分区 inode 被打满的排查过程:定位 /var/cache/fontconfig 暴涨问题

1. 问题现象

在 Ubuntu 服务器上执行:

df -i /

发现根分区 inode 使用率达到 100%:

文件系统         Inodes  已用(I) 可用(I) 已用(I)% 挂载点
/dev/sda2      15556608 15556606       2     100% /

这表示系统并不是单纯“磁盘容量满了”,而是 inode 被耗尽

inode 可以理解为文件系统中“文件/目录的索引节点”。每创建一个文件、目录、软链接,都会消耗一个 inode。

所以即使 df -h 显示磁盘还有空间,只要 inode 满了,系统仍然会报:

No space left on device

常见表现包括:

  • 无法创建新文件
  • 程序写日志失败
  • apt、pip、npm 等工具异常
  • Python / Node / Docker / 浏览器自动化程序异常
  • 系统服务启动失败

2. 初始确认

先同时查看磁盘容量和 inode:

df -h /
df -i /

重点看 df -i /

df -i /

如果 已用(I)% 是 100%,就说明 inode 已经被打满。


3. 第一轮定位:查看哪个目录消耗 inode

一开始尝试直接查多个目录:

sudo du -x --inodes -d1 /var /tmp /home /root /python 2>/dev/null | sort -n

但是这个命令卡住了。

原因是:系统中已经有上千万个小文件,du --inodes 需要递归遍历所有文件,遇到海量文件目录时会非常慢。

因此不要一次扫太大范围,而是分目录排查。


4. 排查 /python

因为当前业务目录在 /python,先怀疑是爬虫或脚本生成了大量文件。

执行:

sudo du -x --inodes -d1 /python 2>/dev/null | sort -n | tail -30

结果类似:

2       /python/dbs
3       /python/__pycache__
5       /python/scrapydweb
8       /python/eggs
26      /python/logs
2388    /python/scrapyd2
5478    /python/Python-3.10.12
5484    /python/Python-3.9.16
11597   /python/scrapyd
25017   /python

结论:

/python 只占用了 25017 个 inode

而根分区总共用了约 1555 万个 inode,所以 /python 不是主因。


5. 排查 /var/lib

继续排查:

timeout 60s sudo du -x --inodes -d1 /var/lib 2>/dev/null | sort -n | tail -30

结果类似:

12206   /var/lib

结论:

/var/lib 也不是主因

6. 分拆排查 /var 下的目录

因为直接扫描 /var 卡住,所以改成逐个目录查:

for d in /var/log /var/cache /var/tmp /var/spool /var/backups /tmp /root /home /opt /usr; doecho "===== $d ====="timeout 60s sudo du -x --inodes -d1 "$d" 2>/dev/null | sort -n | tail -20
done

关键输出:

===== /var/cache =====
14757403   /var/cache/fontconfig
14757689   /var/cache

结论非常明确:

/var/cache/fontconfig 占用了约 1475 万个 inode

这就是根分区 inode 被打满的直接原因。


7. 为什么不能在 /var/cache/fontconfig 里用 ll

进入目录后执行:

ll

会卡住。

原因是:

ll = ls -l

它会尝试读取目录中所有文件,并对每个文件执行 stat 获取详细信息。

当目录里有几百万、上千万个文件时,ll 会像“假死”一样卡住。

在这种目录中不要执行:

ll
ls -l
rm *
rm -rf *

尤其不要执行:

rm -rf *

因为文件太多时可能触发:

Argument list too long

正确做法是使用 find 分批处理。


8. 安全查看目录中的少量文件

如果只是想看几个样本,不要用 ll,可以用:

timeout 5s ls -U /var/cache/fontconfig 2>/dev/null | head -30

或者:

timeout 5s find /var/cache/fontconfig -xdev -maxdepth 1 -type f -printf '%f\n' 2>/dev/null | head -30

查看文件属性样本:

timeout 10s find /var/cache/fontconfig -xdev -maxdepth 1 -type f -print0 2>/dev/null \
| head -z -n 20 \
| xargs -0 -r stat -c 'user=%U group=%G size=%s mtime=%y file=%n'

9. 初步清理 /var/cache/fontconfig

因为 /var/cache/fontconfig 是 fontconfig 字体缓存目录,正常情况下可以删除,系统后续会重新生成。

先退出目录:

cd /

分批删除,比如先删 10 万个文件:

sudo bash -c 'find /var/cache/fontconfig -xdev -maxdepth 1 -type f -print0 2>/dev/null | head -z -n 100000 | xargs -0 -r rm -f'

查看 inode 是否释放:

df -i /

如果有效,再删 100 万个:

sudo bash -c 'find /var/cache/fontconfig -xdev -maxdepth 1 -type f -print0 2>/dev/null | head -z -n 1000000 | xargs -0 -r rm -f'

或者循环删除:

for i in $(seq 1 10); doecho "===== batch $i ====="sudo bash -c 'find /var/cache/fontconfig -xdev -maxdepth 1 -type f -print0 2>/dev/null | head -z -n 500000 | xargs -0 -r rm -f'df -i /
done

也可以一次性删除目录内所有文件:

sudo ionice -c3 nice -n 19 find /var/cache/fontconfig -xdev -mindepth 1 -type f -delete

参数说明:

ionice -c3

表示尽量降低 I/O 优先级,避免影响系统。

nice -n 19

表示降低 CPU 调度优先级。


10. 清理后的结果

清理后再次查看:

df -i /

结果变为:

文件系统         Inodes 已用(I)  可用(I) 已用(I)% 挂载点
/dev/sda2      15556608  807773 14748835       6% /

说明 inode 已经从 100% 降到 6%,系统恢复正常。


11. 发现问题仍在继续:文件还在增加

清理之后发现 /var/cache/fontconfig 里仍然不断有文件增加。

这说明有进程正在持续触发 fontconfig 生成缓存。

为了观察增长情况,可以执行:

watch -n 5 'df -i /; echo; sudo find /var/cache/fontconfig -xdev -maxdepth 1 -type f 2>/dev/null | wc -l'

如果文件数量持续上涨,就说明问题源头还在运行。


12. 初步查看谁在使用 fontconfig

先用 lsof 看谁打开了 /var/cache/fontconfig

sudo lsof -nP 2>/dev/null | grep '/var/cache/fontconfig' | head -50

曾看到类似输出:

gnome-shell   gdm   mem   REG   /var/cache/fontconfig/xxx-le64.cache-7

注意:

mem REG

表示该进程把文件映射到内存使用,通常是读取,并不一定是写入。

所以 gnome-shell 只是使用字体缓存,不一定是元凶。

过滤掉 mem

sudo lsof -nP 2>/dev/null \
| awk '$9 ~ "^/var/cache/fontconfig/" && $4 !~ /^mem/ {print}' \
| head -100

13. 使用 auditd 精准抓写入进程

为了精准定位是谁在写 /var/cache/fontconfig,安装 auditd:

sudo apt update
sudo apt install -y auditd

确认工具存在:

which auditctl
which ausearch

添加监听规则:

sudo auditctl -D
sudo auditctl -a always,exit -F dir=/var/cache/fontconfig -F perm=wa -k fontconfig_write

参数说明:

-F dir=/var/cache/fontconfig

监听这个目录。

-F perm=wa

监听写入和属性变更。

-k fontconfig_write

给这条规则打一个 key,方便后续检索。

等待一段时间后查看日志:

sudo ausearch -k fontconfig_write -i | tail -200

14. 最终定位到元凶

audit 日志中出现了关键证据:

proctitle=node /python/scrapyd/xxx/xx/xxx.js
comm=node
exe=/usr/bin/node
cwd=/python
pid=988264
ppid=874718

同时能看到它在不断操作 /var/cache/fontconfig

name=/var/cache/fontconfig/xxxx-le64.cache-7.NEW nametype=CREATE
syscall=openat success=yes ... O_RDWR|O_CREAT|O_CLOEXECname=/var/cache/fontconfig/xxxx-le64.cache-7 nametype=CREATE
syscall=rename success=yesname=/var/cache/fontconfig/xxxx-le64.cache-7.LCK nametype=DELETE
syscall=unlink success=yes

最终结论:

node /python/scrapyd/xxxx/xx/xxxx.js

正在持续触发 fontconfig 缓存生成,是 /var/cache/fontconfig 文件暴涨、inode 被打满的直接元凶。


15. 停止元凶进程

先查看相关进程:

pgrep -af 'sdenv.js|node'

停止指定脚本:

sudo pkill -TERM -f '/python/scrapyd/xxxxx/xx/xxx.js'

如果没有停止:

sudo pkill -9 -f '/python/scrapyd/xxx/xxx/xxx.js'

再次确认:

pgrep -af 'xxx.js|node'

查看 inode:

df -i /

查看 fontconfig 文件数量:

sudo find /var/cache/fontconfig -xdev -maxdepth 1 -type f 2>/dev/null | wc -l

16. 查父进程

audit 日志中显示:

pid=988264
ppid=874718

查看父进程:

ps -fp 874718

查看进程树:

pstree -ap 874718

也可以查所有相关进程:

pgrep -af 'scrapyd|python|xxxx.js|node'

如果父进程是 Scrapyd 或 Python worker,说明是爬虫任务间接启动了这个 Node 脚本。


17. 取消 auditctl 监听

定位完成后,关闭 audit 规则,避免 audit 日志继续增长。

清空所有临时规则:

sudo auditctl -D

确认规则是否清空:

sudo auditctl -l

如果输出为空,或者没有 fontconfig_write,说明监听已经取消。

如果只想删除这一条规则,可以先查看规则:

sudo auditctl -l

然后删除对应规则:

sudo auditctl -d always,exit -F dir=/var/cache/fontconfig -F perm=wa -k fontconfig_write

不过临时排障场景下,最简单的是:

sudo auditctl -D

18. 再次清理 fontconfig

停止元凶进程后,再清理残留缓存:

cd /
sudo ionice -c3 nice -n 19 find /var/cache/fontconfig -xdev -mindepth 1 -type f -delete

重新生成正常字体缓存:

sudo fc-cache -r -v

查看 inode:

df -i /

19. 为什么 Node 脚本会触发 fontconfig

fontconfig 是 Linux 下的字体配置和缓存系统。以下场景容易触发它生成缓存:

  • Puppeteer
  • Playwright
  • Chromium / Chrome
  • node-canvas
  • sharp
  • SVG / PDF / 图片渲染
  • 服务端截图
  • 浏览器指纹模拟
  • 字体指纹相关逻辑
  • 动态创建字体目录
  • 每次任务创建新的临时浏览器 profile

本次出现大量类似文件:

bcdcb5d5-bff2-4888-a17b-b81202409208-le64.cache-7
1da7dc5a-7b9d-4364-97c6-c8c0e0b8a74d-le64.cache-7
cdd7ba25-f32b-407a-93e4-583a73b042e0-le64.cache-7

这些文件名呈 UUID 风格,说明程序可能不断制造新的字体目录、缓存目录或浏览器环境,导致 fontconfig 不断认为“发现了新字体目录”,于是持续生成新的缓存文件。


20. 检查 sdenv.js

进入目录:

cd /python/scrapyd/xxx/xx

搜索关键字:

grep -nE 'canvas|font|Font|puppeteer|playwright|chromium|chrome|sharp|pdf|svg|tmp|cache|userDataDir|FONTCONFIG|XDG' sdenv.js

搜索整个目录:

grep -RniE 'canvas|font|puppeteer|playwright|chromium|chrome|sharp|userDataDir|FONTCONFIG|XDG' /python/scrapyd/xxxx/xxx 2>/dev/null | head -100

如果是 Node 项目,可以查看依赖:

cd /python/scrapyd/xxx/xx
npm ls canvas puppeteer playwright sharp 2>/dev/null

21. 预防方案

21.1 不要以 root 直接运行 Node 脚本

当前 audit 日志中显示:

uid=root
exe=/usr/bin/node

建议不要让爬虫或 Node 脚本直接以 root 运行。

可以创建普通用户运行爬虫任务,降低影响范围。


21.2 固定缓存目录

运行 Node 前设置独立缓存目录:

mkdir -p /tmp/sdenv-cache/xdg
mkdir -p /tmp/sdenv-cache/fontconfigexport XDG_CACHE_HOME=/tmp/sdenv-cache/xdg
export FONTCONFIG_PATH=/etc/fonts

然后运行:

node /python/scrapyd/xxxx/xxx/sdenv.js

但这不一定能完全阻止 /var/cache/fontconfig 写入,因为系统 fontconfig 配置可能仍然指向 /var/cache/fontconfig


21.3 如果使用 Chromium / Playwright / Puppeteer

要注意:

  • 不要每次创建随机 userDataDir 后不清理
  • 不要让临时 profile 长期堆积
  • 限制并发数量
  • 任务结束后删除临时目录
  • 固定 cache 目录或使用临时目录并定时清理

示例:

--user-data-dir=/tmp/chrome-profile-xxxx
--disk-cache-dir=/tmp/chrome-cache-xxxx

任务结束后:

rm -rf /tmp/chrome-profile-xxxx /tmp/chrome-cache-xxxx

21.4 给 inode 做监控

临时监控:

watch -n 5 'df -i /; echo; sudo find /var/cache/fontconfig -xdev -maxdepth 1 -type f 2>/dev/null | wc -l; echo; pgrep -af "sdenv.js|node|chrome|chromium"'

长期可以写成脚本:

#!/bin/bashwhile true; dodatedf -i /echo "fontconfig file count:"find /var/cache/fontconfig -xdev -maxdepth 1 -type f 2>/dev/null | wc -lecho "related processes:"pgrep -af 'sdenv.js|node|chrome|chromium|playwright|puppeteer'echo "------"sleep 30
done

保存为:

monitor_inode.sh

运行:

bash monitor_inode.sh

22. 本次排障用到的核心命令汇总

查看 inode

df -i /

查看磁盘空间

df -h /

按目录统计 inode

sudo du -x --inodes -d1 /python 2>/dev/null | sort -n | tail -30
sudo du -x --inodes -d1 /var/lib 2>/dev/null | sort -n | tail -30

分目录排查

for d in /var/log /var/cache /var/tmp /var/spool /var/backups /tmp /root /home /opt /usr; doecho "===== $d ====="timeout 60s sudo du -x --inodes -d1 "$d" 2>/dev/null | sort -n | tail -20
done

查看 fontconfig 文件数

sudo find /var/cache/fontconfig -xdev -maxdepth 1 -type f 2>/dev/null | wc -l

安全查看少量文件

timeout 5s ls -U /var/cache/fontconfig 2>/dev/null | head -30

分批删除 fontconfig 缓存

sudo bash -c 'find /var/cache/fontconfig -xdev -maxdepth 1 -type f -print0 2>/dev/null | head -z -n 1000000 | xargs -0 -r rm -f'

一次性删除 fontconfig 缓存

sudo ionice -c3 nice -n 19 find /var/cache/fontconfig -xdev -mindepth 1 -type f -delete

查看相关进程

pgrep -af 'python|node|chrome|chromium|playwright|puppeteer|fc-cache|gnome-shell|gdm'

查看谁打开 fontconfig 文件

sudo lsof -nP 2>/dev/null | grep '/var/cache/fontconfig' | head -50

过滤掉 mem 映射

sudo lsof -nP 2>/dev/null \
| awk '$9 ~ "^/var/cache/fontconfig/" && $4 !~ /^mem/ {print}' \
| head -100

安装 auditd

sudo apt update
sudo apt install -y auditd

添加 audit 监听

sudo auditctl -D
sudo auditctl -a always,exit -F dir=/var/cache/fontconfig -F perm=wa -k fontconfig_write

查询 audit 日志

sudo ausearch -k fontconfig_write -i | tail -200

取消 audit 监听

sudo auditctl -D
sudo auditctl -l

停止元凶进程

sudo pkill -TERM -f '/python/scrapyd/xxxx/xxx/sdenv.js'

如果不停止:

sudo pkill -9 -f '/python/scrapyd/xxxx/xxx/sdenv.js'

查看父进程

ps -fp 874718
pstree -ap 874718

重新生成字体缓存

sudo fc-cache -r -v

23. 最终结论

本次问题不是磁盘容量不足,而是根分区 inode 被打满。

直接原因:

/var/cache/fontconfig

目录中生成了约 1475 万个字体缓存文件。

最终通过 auditd 定位到写入进程:

node /python/scrapyd/xxx/xx/sdenv.js

该 Node 脚本持续触发 fontconfig 创建缓存文件,导致 inode 被迅速耗尽。

处理步骤:

  1. 使用 df -i / 确认 inode 打满;
  2. 使用 du --inodes 分目录定位;
  3. 发现 /var/cache/fontconfig 占用约 1475 万 inode;
  4. 使用 find 分批清理缓存文件;
  5. 安装并使用 auditd 监听写入;
  6. 通过 ausearch 定位到 node /python/scrapyd/xxx/xxx/xxx.js
  7. 停止该进程;
  8. 清理残留缓存;
  9. 取消 audit 监听;
  10. 后续检查 sdenv.js 中的字体、canvas、puppeteer、playwright、chromium、sharp、PDF、SVG 等相关逻辑。

核心经验:

inode 100% 时,不要只看 df -h。
要用 df -i 和 du --inodes 找海量小文件。
遇到千万级目录,不要 ls -l,不要 rm *。
用 find、xargs、auditd 分析和处理。
http://www.rkmt.cn/news/1421808.html

相关文章:

  • 2026五月精选:乌海靠谱的洗衣机回收公司 - LYL仔仔
  • 保姆级教程:手把手教你用U盘给服务器安装VMware ESXi 7.0(附IP配置与登录指南)
  • 2026杭州抖佳信息技术有限公司简介 - 新闻快传
  • 耳机隔音DIY改造指南:从原理到实践,低成本提升被动降噪效果
  • 2026年GEO服务商权威评测:技术深度、实战效果与选型指南 - 资讯焦点
  • ngx_http_core_run_phases
  • 神经网络控制器压缩:组件感知剪枝与稳定性优化
  • 话费卡使用范围科普:回收关键点分享 - 团团收购物卡回收
  • 2026年5月最新淮安GEO优化公司排名TOP5,哪家靠谱不踩坑? - 商业新知
  • 【Web UI 探索】Browser-Use Web UI 项目搭建:让小白也能用界面的 AI 浏览器管家
  • Honey Select 2 HF Patch终极指南:一键安装200+插件,打造完美游戏体验
  • 如何快速解决多屏DPI差异:终极鼠标优化指南
  • 微信立减金回收市场走向规范化,流程迎来全新调整 - 京回收小程序
  • ESXi日志文件在哪里?默认日志目录与排错使用教程
  • 如何用Unlock-Music实现跨平台音乐自由:终极本地解密指南
  • EEG信号处理中的空间插值与跨域对齐技术
  • 2026年优选:浙江灯具生产商 - 品牌推广大师
  • 瑞祥商联卡回收哪种更适合你?按需匹配,省时省力 - 可可收公众号
  • 为什么83%的Lindy自动化项目6个月内失效?,资深CXO团队复盘12个真实崩溃节点
  • Keil MDK调试技巧:硬件与软件断点的原理与应用
  • 合肥黄金回收哪家靠谱?2026 三大品牌对比|附真实成交记录与金价解读 - 润富黄金珠宝行
  • Ubuntu忘记密码重置
  • 从零开始玩转电路设计:用Instructables实现生活创意项目
  • 上海虹口区卖黄金别乱找!2026年5月29日五大黄金回收品牌实测,永兴资质齐全全城最快上门 - 恒顺黄金回收
  • 2026年物联网门户网站哪个强?从流量、资源到服务能力的全方位测评 - 品牌推荐大师
  • 达梦数据库数据页损坏修复实战指南
  • 山东省滨州CPPMSCMP官网报考入口,官方授权双证报考中心 - 众智商学院课程中心
  • 2026年西安本地小区地下室漏水维修正规服务商选型核心要素深度解析 专业防水公司排名推荐(2026年5月防水补漏最新TOP权威排名) - 冠盾建筑修缮
  • 2026年不动产资产管理系统哪家好,集团私有化资管软件对比 - 品牌2025
  • Visual Syslog Server:Windows平台最直观的Syslog日志监控解决方案