首页
关于本站
私人 DNS 加密设置教程
全部文章
推荐
加密 DNS 服务
DNS 实时战报
过滤规则订阅
搜索
网络与 DNS
加密 DNS 实操
路由器与家庭网络
自建服务
AdGuard Home
服务器运维
开发与工具
安全与隐私
登录
搜索
23-4.CN
累计撰写
59
篇文章
累计收到
3
条评论
首页
分类
网络与 DNS
加密 DNS 实操
路由器与家庭网络
自建服务
AdGuard Home
服务器运维
开发与工具
安全与隐私
页面
关于本站
私人 DNS 加密设置教程
全部文章
推荐
加密 DNS 服务
DNS 实时战报
过滤规则订阅
注册丨登录
搜索到
1
篇
标签为
磁盘空间
的文章
2026-10-05
服务器磁盘满了怎么查:df / du / inode / 日志轮转的可执行排查顺序
这篇是服务器运维笔记,和 DNS 无关。站内的加密 DNS 服务在dns.23-4.cn。小服务器的根分区通常很小。我手上这台香港的小机器就是 1.2 GB 的根分区,日常只剩 300 多 MB。这种机器上「磁盘满」不是小概率事件,而是迟早的事——而且它挂起来的样子往往不像磁盘问题:nginx 报 500、PHP 写不了 session、数据库锁不上,你却在查代码。这篇是一份按顺序执行的排查清单,从「确认是磁盘」到「找到元凶」再到「防止复发」。一、先确认是不是磁盘,别急着查别的df -h看三件事:哪个挂载点是满的(Use% 接近或达到 100%);是不是根分区满(/),而不是数据分区——根分区满会连带影响 /tmp、日志、session,表现最杂;Available 是不是真的接近 0。# 记录一个基线,后面所有操作都拿它对比 df -h /还有一个容易被忽略的:inode 用满。df -iinode 满了的表现和磁盘满了几乎一样(写不进去文件),但 df -h 会显示还有空间。大量小文件(session 文件、缓存碎文件、邮件队列)是典型原因。二、找到是谁占的不要一上来 du -sh /*,那会遍历整个文件系统、很慢,还可能把挂载的外部存储也扫进去。用 -x 限制在同一个文件系统:# 第一层:看哪个顶层目录大 du -x -h --max-depth=1 / 2>/dev/null | sort -h # 锁定嫌疑目录后,再往里钻一层 du -x -h --max-depth=1 /var 2>/dev/null | sort -h du -x -h --max-depth=1 /var/log 2>/dev/null | sort -hsort -h 让结果按人类可读单位排序,一眼就能看到最大的。小服务器上最常见的四个元凶:目录原因处理/var/log日志没有轮转,或轮转配置没生效配 logrotate,或直接限制大小/var/lib/nginx/tmp 或类似nginx 把大的上游响应缓冲到磁盘见下面第四节/var/cache/apk(Alpine)包管理器的下载缓存apk cache clean/var/lib/docker镜像和容器层堆积docker system prune(确认后再执行)三、最阴的一种:文件被删了,空间没释放这是排查里最容易卡住的情况:du 加起来明明只有 200 MB,df 却说用掉了 1 GB。原因是有进程还持有已删除文件的句柄。文件在目录里已经看不见了,但 inode 没释放,空间就一直占着。# 找出所有被删除但仍被占用的文件 lsof +L1 2>/dev/null | head -30 # 没有 lsof 时的替代做法 ls -l /proc/*/fd 2>/dev/null | grep deleted | head -30输出里会看到类似 nginx 1234 ... 5u REG ... 500000000 /var/log/nginx/access.log (deleted)——一个 500 MB 的已删除日志。处理方式只有两种:重启那个进程(释放句柄,空间立刻回来);或者不要重启,用 truncate 清空当前文件(如果进程还在往里写新文件的话)。注意:rm 一个正在被写的日志文件不会释放空间,只是把它变成「不可见的占用」。正确做法是 truncate -s 0 file.log 或让 logrotate 用 copytruncate。四、nginx 把响应缓冲到了磁盘nginx 的 error.log 里会出现这种警告:[warn] an upstream response is buffered to a temporary file /var/lib/nginx/tmp/fastcgi/1/98/0000002981 while reading upstream这不是错误,但它说明上游(PHP-FPM)返回的响应超过了内存缓冲区,nginx 把它落盘了。如果上游返回很大的响应(比如一个几百 KB 的 HTML、或者一个大的 JSON 接口),这些临时文件会持续产生。两个方向:# 1. 让缓冲区能装下正常的响应(按你的实际响应大小调) fastcgi_buffers 16 16k; fastcgi_buffer_size 32k; # 2. 给临时目录设上限,避免无限增长 fastcgi_max_temp_file_size 64m; fastcgi_temp_path /var/lib/nginx/tmp/fastcgi 1 2;另外要确认临时目录会被清理。nginx 正常情况下会自己删,但如果进程被强杀过,残留文件会留在那里:du -sh /var/lib/nginx/tmp/* 2>/dev/null find /var/lib/nginx/tmp -type f -mtime +1 2>/dev/null | head五、日志轮转:一次配好,长期省心# /etc/logrotate.d/myapp /var/log/myapp/*.log { daily rotate 7 maxsize 50M # 单个文件超过 50M 就轮转,不等第二天 missingok notifempty compress delaycompress copytruncate # 关键:不重启进程也能释放空间 }maxsize 和 copytruncate 这两行是关键:maxsize 让「一天涨 2 GB」这种突发情况当天就被截住;copytruncate 避免「轮转后进程还拿着旧句柄」的问题——也就是第三节那个坑。Alpine 上 logrotate 不在默认安装里,要单独装:apk add logrotate # 确认 cron 里有这一行,否则 logrotate 根本不会跑 grep logrotate /etc/crontabs/root /etc/periodic/daily/* 2>/dev/null最容易犯的错是配好了 logrotate 但没验证它真的执行过。 用 logrotate -d(dry-run)先看一遍:logrotate -d /etc/logrotate.d/myapp六、给根分区留出安全垫在小分区上,与其等它满了再救,不如主动留垫:把日志目录单独挂载(或软链到数据盘),别让日志吃掉根分区;给关键服务设置自己的上限:journald 的 SystemMaxUse、docker 的 log-opts max-size、nginx 的 temp 上限;加一条最简单的告警,超过 85% 就提醒:#!/bin/sh # /etc/periodic/daily/check-disk THRESHOLD=85 USED=$(df / | awk 'NR==2 {gsub("%","",$5); print $5}') if [ "$USED" -ge "$THRESHOLD" ]; then echo "root filesystem ${USED}% full on $(hostname)" | \ mail -s "disk warning" you@example.com fi在改动前后都记一次 df -h /。这样你能明确知道「这次操作多占了多少」——尤其是往服务器上传东西的时候。七、完整流程回顾df -h # 1. 确认哪个分区满 df -i # 2. 顺便看 inode du -x -h --max-depth=1 / # 3. 找出大目录 lsof +L1 # 4. 查「已删除但被占用」的文件 # 5. 处理:清缓存 / 轮转日志 / 重启持有句柄的进程 # 6. 配 maxsize + copytruncate,防止复发 # 7. 加一个 85% 的告警顺序很重要:先量,再改。跳过第 3、4 步直接去删东西,很容易删掉不该删的,而真正的元凶还在那儿。相关阅读Alpine 轻量服务器初始化清单:时钟、Nginx、PHP 一篇配齐阿里云 2 元/月服务器防天价账单:流量监控脚本实操在 Alpine Linux 上从零搭一个 Typecho:nginx + php-fpm + SQLite 的完整清单
2026年10月05日
86 阅读
0 评论
0 点赞