云服务器磁盘使用率达到百分之百后,数据库可能无法写入,Nginx 可能停止记录日志,软件更新也会失败。此时最危险的做法是直接进入 /var/log 执行批量删除:文件可能仍被进程占用,删错路径还会破坏系统,而且未经备份的日志会失去审计价值。
正确处理顺序是先确认哪个文件系统或 inode 耗尽,再用 du、ncdu 和 find 定位目录与文件,最后针对日志、缓存、容器数据或业务文件选择对应方案。这篇文章给出可直接执行的排查命令,并明确标注删除风险、备份方法和更安全的替代操作。
先用 df 判断容量、inode 还是已删除文件问题
先记录现场,不要立刻清理:
date
df -hT
df -i
lsblk -f
findmnt
df -hT 显示文件系统类型、总量、已用量和挂载点。重点找 Use% 接近百分之百的行,并确认它对应 /、/var、数据盘还是容器盘。df -i 检查 inode;大量零字节或小文件也可能让 inode 用尽,此时容量还有剩余,系统仍无法创建新文件。
| 现象 | 可能原因 | 下一步 |
|---|---|---|
| 某挂载点容量接近满 | 大日志、备份、上传、容器层、数据库文件 | 用 du 和 find 在该挂载点内定位 |
| inode 使用率接近满 | 海量小文件、会话、缓存、邮件队列 | 按目录统计文件数量并查生成来源 |
df 很满但 du 对不上 |
文件已删除但仍被进程打开、挂载覆盖、权限不可读 | 用 lsof +L1 和 findmnt 排查 |
| 根分区正常但应用报无空间 | 独立数据盘、配额、只读文件系统或保留块 | 查应用实际路径、挂载与内核日志 |
df 统计文件系统分配,du 统计可见目录项,两者口径不同。如果日志被删除时服务仍保持文件描述符,目录里看不到它,但占用不会释放。安装并使用 lsof:
# RHEL、Rocky、CentOS
sudo dnf install -y lsof
# Debian、Ubuntu
sudo apt update
sudo apt install -y lsof
sudo lsof +L1
输出中 NLINK 为零的文件就是已删除但仍打开的文件。更安全的释放方式是确认对应服务后,在维护窗口平滑重载或重启,让它关闭旧文件描述符。不要随意终止数据库进程,也不要直接操作陌生的 /proc/,否则可能造成数据损坏或业务中断。
还要留意挂载覆盖。例如,某目录原本写入了大量数据,后来又挂载新磁盘,旧数据会被遮住,du 从当前路径看不到。使用 findmnt 和部署记录确认挂载变化,不要贸然卸载生产数据盘。
用 du、ncdu 和 find 定位大目录与大文件
确定满的是根文件系统后,从同一挂载点逐层检查。-x 可以避免跨入其他文件系统:
sudo du -xhd1 / 2>/dev/null | sort -h
如果 /var 最大,再继续:
sudo du -xhd1 /var 2>/dev/null | sort -h
sudo du -xhd1 /var/log 2>/dev/null | sort -h
du 扫描目录会产生磁盘读取,在文件数量极大的生产服务器上可能影响业务。优先从已知大目录开始,在低峰期执行,并使用 nice 和 ionice 降低排查任务的优先级:
sudo ionice -c2 -n7 nice -n 19 du -xhd1 /var
若希望交互浏览,可以安装 ncdu:
# RHEL、Rocky、CentOS;可能需要扩展仓库
sudo dnf install -y ncdu
# Debian、Ubuntu
sudo apt update
sudo apt install -y ncdu
sudo ncdu -x /var
ncdu 可以按目录大小排序。它也支持交互删除,但生产环境不建议在界面中边看边删,因为容易误选且不便审计。把它作为定位工具,记录路径后退出,再单独确认文件所有者、用途、备份和清理方式。
查找当前文件系统中超过一吉字节的普通文件:
sudo find / -xdev -type f -size +1G -printf '%s\t%p\n' 2>/dev/null | sort -nr | head -n 50
若目标是独立挂载的 /data,把起始路径改成 /data。-xdev 不跨文件系统,能避免扫描网络盘和其他挂载。按修改时间找出三十天未变的文件时,先只打印,不要直接加 -delete:
sudo find /var/log -xdev -type f -mtime +30 -printf '%TY-%Tm-%Td %10s %p\n' | sort
文件旧不代表可以删除。数据库归档、合规日志和业务上传都可能需要长期保留。应与文件所有者确认保留周期,检查是否还有硬链接、进程占用或备份任务依赖。
inode 用尽时,可逐层统计文件数量。下面命令会遍历指定目录,文件极多时同样应在低峰执行:
sudo find /var -xdev -type f -printf '%h\n' 2>/dev/null | sort | uniq -c | sort -nr | head -n 30
会话目录、缓存目录或邮件队列中出现数百万小文件时,先修复清理策略和生成速度,再按应用官方方式清理。单纯删除一批文件而不修根因,磁盘很快会再次耗尽。
安全清理 systemd、应用和容器日志
限制 systemd journal 占用
先查看 journal 当前空间:
sudo journalctl --disk-usage
按总容量保留到五百兆字节,可先轮转当前活动日志,再清理旧归档:
sudo journalctl --rotate
sudo journalctl --vacuum-size=500M
sudo journalctl --disk-usage
--vacuum-size 主要删除已归档的旧 journal,保留量是目标上限附近,不应理解为精确字节。也可以使用 --vacuum-time=14d 按时间保留,但容量策略与审计要求要先确认。若服务器需要保存更长安全日志,应先转发到远端日志平台或备份,再执行清理。
长期可在 /etc/systemd/journald.conf 中配置 SystemMaxUse、SystemKeepFree 等参数。修改前备份文件,变更后重启 systemd-journald 会影响日志服务,应在维护窗口验证。比起故障时临时清理,预先设置容量上限更可靠。
处理普通文本日志
先确认文件大小、类型、最近更新时间和占用进程:
sudo ls -lh /var/log/myapp/
sudo file /var/log/myapp/app.log
sudo lsof /var/log/myapp/app.log
删除风险提示:不要对 /var/log、/var/lib 或任何变量为空的路径执行 rm -rf,也不要复制网上的通配符删除命令。rm 删除通常不进入回收站,路径写错会造成不可逆损失;日志被进程打开时,直接删除目录项还可能出现“文件看不到但空间未释放”。删除前必须用 du 和 ls 再次确认完整路径,核对服务与保留要求,并把重要内容备份到另一块磁盘或远端存储。
如果 /mnt/backup 确认是空间充足的独立备份盘,可以压缩备份单个日志:
findmnt /mnt/backup
df -h /mnt/backup
sudo gzip -c /var/log/myapp/app.log > /mnt/backup/app.log.$(date +%F-%H%M%S).gz
sudo gzip -t /mnt/backup/app.log.*.gz
通配符校验可能匹配多个文件,正式操作时最好写入刚生成的准确文件名。若没有独立备份盘,应先传到受控远端,不要在已经满的同一文件系统内复制大文件。
对仍在写入的日志,优先配置并执行 logrotate,让服务重新打开文件。紧急情况下,在完成备份、确认文件确实只是可丢弃日志并获得批准后,可受控截断:
sudo truncate -s 0 /var/log/myapp/app.log
truncate 会立即丢弃该文件现有内容,仍属于破坏性操作,只是不会删除目录项,服务可继续使用同一个文件描述符。必须写准确绝对路径,执行前用 du -h、ls -l 和 lsof 确认。对数据库数据文件、二进制日志、WAL、队列或未知文件绝不能使用此命令。
若确实要删除一个已确认无进程占用、已有可恢复备份的普通旧文件,至少使用交互确认并阻止以连字符开头的路径被解析为选项:
sudo rm -i -- /完整路径/已确认的旧文件
这不是首选清理方案。能通过应用保留策略、logrotate、归档工具或 truncate 处理的日志,不应直接 rm。执行后还要复查服务和磁盘,而不是假设空间一定释放。
检查容器日志和镜像
Docker 默认 JSON 日志可能持续增长。先查看整体占用:
docker system df -v
sudo du -h /var/lib/docker/containers/*/*-json.log 2>/dev/null | sort -h | tail -n 20
不要直接对 /var/lib/docker 执行批量删除,那里包含镜像层、容器状态和数据卷。docker system prune -a 也不是通用清理命令,它可能删除停用容器和后续回滚所需镜像。应先用 Docker 自身命令确认对象是否仍被使用,并为容器配置日志轮转,例如在 /etc/docker/daemon.json 中设置 json-file 的 max-size 与 max-file,修改前备份配置并用测试节点验证。
数据卷可能保存数据库与上传文件,不能按“未运行容器”就判定无用。任何卷清理都应找到业务所有者、挂载关系和备份,完成恢复验证后再处理。
清理软件缓存、临时文件并考虑扩容
发行版包缓存通常可以安全重建,但清理后下次安装需要重新下载。RHEL、Rocky、CentOS 使用:
sudo dnf clean all
旧版可使用:
sudo yum clean all
Debian、Ubuntu 使用:
sudo apt clean
查看 /tmp 前应确认应用是否正在使用临时文件。相比手工删除,优先使用 systemd 的临时文件规则:
systemd-tmpfiles --cat-config
sudo systemd-tmpfiles --clean
它只按已配置策略处理文件,但仍应先了解规则。生产应用可能把长任务中间文件放在临时目录,错误的过期策略会影响任务,因此要先在测试环境验证。
如果增长来自有效业务数据,清理只是推迟故障,应扩容磁盘或迁移数据。先识别分区与文件系统:
lsblk -f
df -hT
findmnt /目标挂载点
云盘扩容通常分为控制台扩大块设备、扩展分区、扩展文件系统三个阶段。不同平台、分区表、LVM、ext4 与 XFS 的命令不同,不能在不知道设备名时照抄。操作前创建快照与异地备份,阅读平台文档,并在维护窗口完成。常见的文件系统扩展工具是 ext4 的 resize2fs 和 XFS 的 xfs_growfs,但它们必须作用于正确设备或挂载点。
不要尝试通过删除系统库、内核、包数据库或 /var/lib 下的未知内容换空间。若磁盘已经完全写满,可以先从已确认可重建的包缓存、受控 journal 保留和已备份应用日志释放少量空间,再让数据库和系统恢复写入,然后安排正式扩容。
用 logrotate 和监控防止再次写满
logrotate 可以按时间或大小轮转文本日志,并保留指定份数。下面是 /etc/logrotate.d/myapp 的示例:
/var/log/myapp/*.log {
daily
rotate 14
size 100M
compress
delaycompress
missingok
notifempty
create 0640 myapp myapp
sharedscripts
postrotate
/bin/systemctl kill -s HUP myapp.service >/dev/null 2>&1 || true
endscript
}
daily 表示每天检查,size 100M 让大日志达到条件时轮转,rotate 14 保留十四份,compress 压缩旧文件。create 的用户和组必须替换为真实服务账号。postrotate 通过 HUP 请求程序重新打开日志,前提是该服务支持该信号;不支持时应使用应用官方重载方式。
不要随意使用 copytruncate。它适合无法重新打开日志的少数程序,但复制与截断之间存在写入丢失窗口,大日志复制还会产生额外 I/O。能让应用规范重新打开文件时,应优先采用重命名加信号方式。
先用调试模式检查规则,不实际轮转:
sudo logrotate -d /etc/logrotate.conf
确认路径、权限和脚本都正确后,再等待定时任务执行。若要在维护窗口强制测试,可以使用 logrotate -f,但它会真的轮转所有命中规则,必须先评估并尽量只测试单独配置文件。
监控至少覆盖文件系统容量、inode、日增长量和预测耗尽时间。可以设置多个阈值,例如达到百分之七十提醒趋势、百分之八十五告警、百分之九十五触发紧急响应,但具体值应根据扩容速度和业务波动调整。数据库盘还应保留足够空间应对临时表、索引重建和恢复操作。
日志策略要同时定义保留天数、单文件上限、压缩、远端归档与合规要求。只设置“保留十四天”但不限制单文件大小,突发错误仍可能在几小时内写满磁盘。应用发生异常日志风暴时,还要修复错误重试和日志级别,不能完全依赖轮转。
常见问题
df 显示很满,du 却找不到大文件怎么办?
先运行 lsof +L1 查已删除但仍打开的文件,再检查挂载覆盖、权限和文件系统保留空间。确认进程后平滑重载或重启,通常可以释放被占用的已删除文件。
日志太大能直接删除吗?
不建议。先确认路径、内容、占用进程和保留要求,并备份到独立存储。优先使用 logrotate;紧急时只对明确的文本日志执行受控 truncate,不能处理数据库文件。
journalctl --vacuum-size 为什么没有精确降到目标值?
它处理的是可清理的归档日志,并受活动日志和文件粒度影响。可先执行 journalctl --rotate,再清理并复查 --disk-usage。
inode 满了但容量没满,扩容有用吗?
扩容可能增加 inode,但没有修复海量小文件持续产生的根因。应先定位文件最多的目录,按应用策略清理并修复会话、缓存或队列的生命周期。
云盘扩容后为什么 df 仍没变化?
控制台扩容通常只扩大块设备,还需要根据分区、LVM 和文件系统类型执行后续扩展。操作前备份,并严格使用平台与发行版对应步骤,不能凭设备名猜测。
总结
- 磁盘告警先用
df -hT、df -i和findmnt判断具体文件系统、inode 与挂载问题,再开始扫描。 - 使用
du、ncdu和只打印结果的find逐层定位,文件量大时在低峰降低扫描优先级。 df与du不一致时重点检查已删除但仍打开的文件,优先平滑重载服务释放空间。- 日志清理前必须确认并备份,优先使用
journalctl --vacuum-size、logrotate或受控truncate,禁止粗暴批量rm。 - 有效业务数据持续增长时应扩容或迁移,并通过日志轮转、容量与 inode 告警、增长预测防止再次写满。
企业QQ咨询




