惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Blog — PlanetScale
Blog — PlanetScale
SecWiki News
SecWiki News
Google DeepMind News
Google DeepMind News
WordPress大学
WordPress大学
小众软件
小众软件
C
CERT Recently Published Vulnerability Notes
Jina AI
Jina AI
N
Netflix TechBlog - Medium
GbyAI
GbyAI
IT之家
IT之家
Apple Machine Learning Research
Apple Machine Learning Research
AWS News Blog
AWS News Blog
G
GRAHAM CLULEY
L
Lohrmann on Cybersecurity
C
Cybersecurity and Infrastructure Security Agency CISA
I
Intezer
T
Tor Project blog
P
Palo Alto Networks Blog
P
Privacy & Cybersecurity Law Blog
P
Privacy International News Feed
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
P
Proofpoint News Feed
T
Tailwind CSS Blog
C
Check Point Blog
Cloudbric
Cloudbric
Y
Y Combinator Blog
The Last Watchdog
The Last Watchdog
Forbes - Security
Forbes - Security
Last Week in AI
Last Week in AI
S
Security Affairs
博客园 - Franky
F
Fortinet All Blogs
量子位
M
MIT News - Artificial intelligence
C
Cisco Blogs
酷 壳 – CoolShell
酷 壳 – CoolShell
Stack Overflow Blog
Stack Overflow Blog
S
Secure Thoughts
V
Visual Studio Blog
AI
AI
美团技术团队
B
Blog RSS Feed
Application and Cybersecurity Blog
Application and Cybersecurity Blog
博客园 - 三生石上(FineUI控件)
阮一峰的网络日志
阮一峰的网络日志
Engineering at Meta
Engineering at Meta
人人都是产品经理
人人都是产品经理
Microsoft Security Blog
Microsoft Security Blog
T
Threatpost
Cyberwarzone
Cyberwarzone

暗无天日

读:AI Agent 安全日志——从可见性与隐私的两难说起 - 暗无天日 AI写作的语言指纹——如何让文字不那么像机器 - 暗无天日 读:50 条 Claude Code 技巧——一个工程经理的六个月使用心得 读:AI 辅助开发为什么让 E2E 测试更有价值 - 暗无天日 读:在Emacs中使用Claude Code(Spacemacs适配版) - 暗无天日 Claude Code 背后的工程哲学——读 Agent Harness Engineering 读:Agent Harness Engineering——AI 智能体不只是模型,还有套件 - 暗无天日 browser-harness:让 AI 直接接管你的浏览器 - 暗无天日 读:Security-First CI/CD —— DevSecOps 自动化实践指南 TIL: 数字小键盘的小数点陷阱与行内算术求值 - 暗无天日 读:Immutability 不是万能药,它是一种权衡 - 暗无天日 Conducty:给 Claude Code 加上项目记忆和并行执行能力 - 暗无天日 读 — GitHub Trending 里的 Claude Code 技能包 读 — Prompt Caching 省钱指南 TIL: Emacs 中那些跟鼠标配合的冷门快捷键 - 暗无天日 读:Anvil——把 Emacs 变成 AI 的工具服务器 读:Emacs 代码折叠终极指南 - 暗无天日 读:Clojure 搭车客指南 - 暗无天日 git推送失败后恢复仓库损坏的完整记录 - 暗无天日 多智能体系统的两个有效模式——以及对 Claude Code 用户的启示 - 暗无天日 用 Org Babel 写 Literate 博文:扩展执行 + 定制导出 proced:Emacs 内置的进程查看器 - 暗无天日 从 proced 定制中学到的 Elisp 模式 读:让 Emacs proced 在 macOS 上显示 CPU 和内存 异步编程的函数着色税 - 暗无天日 链式调用的代价:JavaScript 和 Clojure 的共同教训 - 暗无天日 hyperfine:命令行基准测试工具 - 暗无天日 管道中的变量去哪了?——子 shell 作用域陷阱 - 暗无天日 开源包装器的信任陷阱:四个危险信号 - 暗无天日 程序员愿意为 AI 写文档,却不愿为同事写 - 暗无天日 mktemp: Shell 脚本中临时文件的安全陷阱与最佳实践 - 暗无天日 WSL9x —— 在 Windows 9x 里跑 Linux 内核 6.19 用 ox.el 做你想做的事 —— org-export 高级编程指南 读:Hot-wiring the Lisp Machine —— 用纯 Elisp 构建零依赖的 Org 静态站点生成器 Elisp 性能优化的六个实战教训 - 暗无天日 fcitx5 下 Emacs 无法切换输入法的排查 - 暗无天日 ERT 测试交互命令的三种方式 - 暗无天日 SEM Assistant: 当 Elisp 守护进程遇上 LLM 用 dmsg 给 Elisp 加上结构化调试日志 用 org-habit 追踪非每日习惯 - 暗无天日 Clojure X-Men:当编程语言特性变成超能力 - 暗无天日 TIL: 用 diff-hl 在 fringe 中显示 git 变更 读:llm-test —— 用 LLM agent 驱动 Emacs 测试 TIL: AI 时代的橡皮鸭调试 - 暗无天日 fcitx 启动后键盘输入卡顿的排查 - 暗无天日 TIL: 早期网页的图片热区导航 - 暗无天日 读 Seeing the Whole System 用 Emacs 自动生成每周链接推荐 - 暗无天日 读:ASCII control characters in my terminal 读 What to learn - 暗无天日 Lisp 的括号之痛——一个愚人节玩笑揭开的老伤疤 - 暗无天日 一本书该"线性读"还是"并行读" - 暗无天日 读 How to Monetize a Blog:一篇伪装成变现指南的讽刺文 Python Mock 第三方依赖的四种策略 - 暗无天日 Emacs Lisp 热重载实用指南 - 暗无天日 Prot 的 Emacs 配置哲学 - 暗无天日 TIL: 从直播对谈中学到的三个 Emacs 技巧 - 暗无天日 TIL: 自动使用项目虚拟环境的 Python - 暗无天日 TIL: 让 Help buffer 自动获得焦点 一条命令让本地开发用上 HTTPS —— slim 工具介绍 用 fsck 检查和修复 Linux 文件系统 排查Linux进程"卡死"实战:从strace到gdb全流程 - 暗无天日 PostgreSQL 索引:从基础到你可能不知道的高级用法 - 暗无天日 用 .pdbrc 自定义 Python 调试器 ANSI 转义码的标准化现状 - 暗无天日 终端程序的潜规则 - 暗无天日 PARA Org-mode 测试配置 - 暗无天日 AI越强越辣鸡?控制论说这是必然的 - 暗无天日 AI 越强越需要你盯着——反馈循环实操指南 - 暗无天日 你的AI代理正在偷你的密钥——四种你没想到的泄露通道 - 暗无天日 LLM 在 DevOps 中的三种角色 - 暗无天日 写作风格的反建议 - 暗无天日 反驳本质复杂性——Dan Luu 论为什么《没有银弹》错了 - 暗无天日 文件充满了危险——Dan Luu 谈文件系统的可靠性陷阱 - 暗无天日 AI 时代的 PARA 方法:用 Org-mode 和 AI 打造个人知识管理系统 Linux 数据去重学习笔记 - 暗无天日 创建跨平台 ZIP 文件的隐藏陷阱:Extra Field - 暗无天日 X11 Forwarding 排障指南 - 暗无天日 IP欺骗端口扫描:当别人冒充你去扫描别人 - 暗无天日 Linux 输入栈全景解析:从硬件按键到屏幕响应 - 暗无天日 Unix 系统中那些被埋没的配置开关——以 FontConfig 为例 - 暗无天日 在Linux上限制儿童使用电脑 - 暗无天日 GIF不仅仅是一种图片格式——用GIF流做些奇怪的事 - 暗无天日 Leiningen 学习笔记:Clojure 项目构建与管理从入门到实战配置 - 暗无天日 Google SRE Book 读书笔记 - 暗无天日 yes 管道 head 发生了什么 - 暗无天日 为什么 nohup 在 crontab 中不起作用 Bash中的Indirection与Nameref - 暗无天日 Linux PAM 简介 - 暗无天日 从Linux ISO文件启动计算机 - 暗无天日 用 Bash 打造一个Screen Locker 用GitHub Actions自动构建EGO博客 - 暗无天日 blocking I/O 的作用 - 暗无天日 mobileog 手机端同步提示Error:2 No such file 的解决方法 回收 WSL2 VHDX 文件占用空间 使用 org-mode columnview 生成任务列表 - 暗无天日 Emacs 作为 MPD 客户端 - 暗无天日 移动文件路径却不破坏org file link的方法 - 暗无天日 如何合理的导出help link 成HTML - 暗无天日 笑话理解之Biology - 暗无天日
读:df 与 du——为什么两个磁盘用量命令数字对不上 - 暗无天日
2026-05-19 · via 暗无天日

半夜三点,监控告警:磁盘 80%。你登上服务器,顺手跑了 du -sh / ,结果回了个 50%。又跑了两遍,数字还是对不上。你没看错,命令也没坏。

TecMint 上有篇文章把这个现象拆得很清楚: dfdu 量的根本是两件不同的事。数字对不上不是 bug,是 Linux 文件系统的设计使然。知道差在哪,排查方向就有了。

机制:两个命令量的不是同一个东西

df 不扫描目录,不检查文件。它直接读文件系统的超级块(superblock),问内核一句话:"当前有多少磁盘块被标记为'已分配'?"

超级块是文件系统的账本,记录着整个分区的块分配情况。内核分配一个块、释放一个块,都更新超级块。 df 只是在某个瞬间翻了一下这本账。

du 的工作方式完全相反。它从你指定的路径出发,一颗一颗地遍历目录树,统计每一个能看见的文件和目录的大小,最后加总。

df 量的是"文件系统层面"——哪些块被占了。 du 量的是"目录树层面"——哪些文件我能看见。

这两层之间的灰色地带,就是差异的来源:磁盘块在文件系统层面被标记为"已分配",但在目录树里找不到对应的文件。 df 能看到这些块, du 看不到。

最常见原因:删了文件,但进程还抓着不放

sudo lsof +L1 | sort -k7 -rn

rm 删除文件时,Linux 只做了两件事:

  1. 从目录里拿掉这个文件名
  2. 把 inode 的 link count 减 1

磁盘上的数据本身没有动。

此时 du 立刻看不到这个文件了。但如果有个进程在 rm 之前就打开了这个文件(比如 nginx 正在写 access.log ),内核不会释放那些磁盘块——进程还在用。 df 仍然把它们计为"已分配"。

直到进程关闭文件描述符(退出或重启),内核才释放磁盘块, df 的数字才降下来。

典型场景:运维看到磁盘快满了, rm 掉一个几十 GB 的日志文件, df 一看——数字完全没动。

关于这个话题,之前写过一篇Linux 删文件的真相——用 /proc 恢复被进程持有的已删除文件,讲了 lsof +L1 的输出怎么读、怎么从 /proc/PID/fd/ 把数据捞回来、怎么用 hard link 预防。本文不再重复,重点讲已删除文件之外的其他原因。

一个检测脚本:有没有已删除但未释放的文件

在说其他原因之前,先把检查封装成一个脚本。放到服务器上,半夜三点直接跑:

bash
set -e

echo "=== 已删除但进程仍持有的文件 ==="
echo

TEMP=$(mktemp)

sudo lsof +L1 2>/dev/null | awk '
NR>1 {
  size = $7
  if (size ~ /^[0-9]+$/) {
    total += size
    # 从第10个字段开始拼文件名(lsof 的 NAME 列从字段10开始)
    name = ""
    for (i = 10; i <= NF; i++) name = name $i " "
    printf "  %-10s  PID=%-8s  FD=%-5s  %s\n", humansize(size), $2, $4, name
  }
}
function humansize(s,    u, v) {
  u = "BKMGTP"
  v = s
  while (v >= 1024 && length(u) > 1) {
    v /= 1024
    u = substr(u, 2)
  }
  return sprintf("%.1f%s", v, substr(u, 1, 1))
}
END {
  if (total == 0) {
    print "  没有发现已删除但仍被持有的文件。"
  } else {
    printf "\n  总计占用: %s\n", humansize(total)
    printf "  (这部分空间 df 计入,du 看不到)\n"
  }
}' > "$TEMP"

cat "$TEMP"
rm -f "$TEMP"

脚本做的事:遍历 lsof +L1 的输出,把每个文件的 SIZE 列加起来,换算成人类可读的大小,末尾汇总一个总计。那个总计数字,就是 df 能看到但 du 看不到的空间。

其他让数字对不上的原因

文件系统保留块

ext 系列文件系统默认把 5% 的磁盘空间预留给 root 用户。这部分空间不属于任何文件, du 根本看不到它们;而 df 虽然不把它们列入"Used"列,但 df 的"Available"列已经扣掉了这部分——也就是说, du 加总出来的数字永远够不到 df 的"Size",差值里有 5% 是文件系统提前圈走的。

查看保留块大小(仅 ext2/3/4,XFS 用 xfs_info ,Btrfs 无直接等价命令):

sudo tune2fs -l /dev/sda1 | grep -i "reserved block"
Reserved block count:     655360
Reserved blocks uid:      0 (user root)

如果磁盘很大(TB 级),5% 是一个可观的数字。非系统盘可以考虑调低这个比例:

sudo tune2fs -m 1 /dev/sdb1

-m 1 的意思是只保留 1%。但别在根分区上这么干——/ 一旦满了连 root 都写不进去,系统就没法操作了。

隐藏挂载点

如果你先在一个目录里写满了数据,后来又在这个目录上挂载了其他分区,那么即使原来的数据还在,你已经看不到了:

dd if=/dev/zero of=/tmp/bigfile bs=1M count=500

sudo mount /dev/sdb1 /tmp

此时 du -sh / 看不到 /tmp/bigfile ,因为 /tmp 现在指向的是新分区的根。但 df 看的是 / 所在的分区——那个 500MB 的文件块还在上面,占着空间。

排查方法:用 bind mount 把 / 重新暴露到一个干净路径下,再看一遍:

sudo mkdir /mnt/root_inspect
sudo mount --bind / /mnt/root_inspect
du -sh /mnt/root_inspect/tmp

如果数字比 du -sh /tmp 大很多,挂载点底下有被遮住的数据。

容器和 overlay 文件系统

容器运行时(Docker、Podman 等)用 overlay 文件系统把多个层叠在一起。容器的写操作存在 upper 层,删除操作用"白文件"标记。overlay 自己的空间统计机制和底层文件系统的超级块统计不完全对齐,尤其是在大量删除容器镜像层之后。

这种情况排查比前几种复杂,通常先确认前三种原因都不成立,再看是不是容器导致的。

排查三步

先找出已删除但仍占空间的文件,按大小排:

sudo lsof +L1 | sort -k7 -rn | head -10

九成情况到这一步就找到了——基本都是一个被 rm 掉的日志,nginx 或 Java 进程还抓着 fd 往里写。

然后释放空间。两条路。

能重启的话,干净利落:

sudo systemctl restart nginx

进程重启关闭所有文件描述符,内核回收磁盘块, df 马上反映。

如果生产环境不能停服,从 /proc 把文件清掉:

sudo truncate -s 0 /proc/1423/fd/10

truncate -s 0 把文件大小设为零。进程的 fd 还开着,继续往里写,但原来的空间已经释放, df 立刻见效。

警告:数据库 write-ahead log、任何进程用于 crash recovery 的文件都别碰。数据会坏。只对普通应用日志用这一招,因为丢了内容也无所谓。

最后确认空间回来了:

df -h /var/log

如果还是没降,回头看看是不是还有别的进程也持有已删除文件,或者检查保留块和隐藏挂载点。

工具速查表

场景 命令
文件系统到底满没满 df -h
哪个目录吃空间最多 du -sh /* | sort -rh
为什么删了文件空间没回来 =sudo lsof +L1 sort -k7 -rn=
文件系统给自己留了多少余量 =sudo tune2fs -l /dev/sdX grep -i reserved=
挂载点底下有没有藏着数据 sudo mount --bind / /mnt/inspect && du -sh /mnt/inspect/ 挂载点路径

再碰到半夜三点磁盘告警,先跑检测脚本,再看工具速查表。九成情况, lsof +L1 的前几行就把答案摊在你面前。