前言
“No space left on device” —— 这大概是所有后端开发和运维最不想看到的报错之一。
当磁盘写满时,MySQL 可能会崩溃,日志无法写入,甚至 Tab 键补全都会失效。很多人的第一反应是:“完了,快删点东西!”但如果不知道谁占用了空间,盲目删除可能会导致更严重的系统故障。
今天我们来分享一套标准化的磁盘清理流程,助你在危急时刻冷静救火。
第一步:宏观定位——是哪块磁盘满了?
首先,我们需要知道是系统盘(/)满了,还是数据盘(/data)满了。 使用 df 命令(Disk Free):
Bash
# -h 代表 human-readable,以 G, M 为单位显示 df -h
输出示例:
Plaintext
Filesystem Size Used Avail Use% Mounted on /dev/vda1 40G 38G 2.0G 95% / devtmpfs 3.9G 0 3.9G 0% /dev /dev/vdb1 100G 20G 80G 20% /data
分析:很明显,根目录 / 下的 /dev/vda1 使用率达到了 95%,是它出了问题。
第二步:精准打击——谁吃掉了我的空间?
知道是根目录满了,但根目录下文件夹那么多,总不能一个个 ls 去看吧? 我们需要用到 du 命令(Disk Usage)。
这里教大家一个**“黄金组合命令”**,能快速找出当前目录下最大的前10个文件夹:
Bash
# 切换到根目录(或者你发现满的那个挂载点) cd / # 查找当前目录下各个文件夹的大小,并按大到小排序,显示前10个 du -h --max-depth=1 | sort -hr | head -n 10
命令解析:
du -h --max-depth=1:只统计当前目录下一级子目录的大小,不递归显示所有文件。sort -hr:按人类可读的数字格式(human-readable)逆序(reverse)排序。head -n 10:只看前10名。
输出示例:
Plaintext
38G . 15G /var 10G /usr 8.5G /home ...
排查思路:发现 /var 目录巨大。好的,进入 /var,再次执行上面的组合命令。cd /var -> 执行命令 -> 发现 /var/log 巨大。cd /var/log -> 执行命令 -> 发现 catalina.out 或者 access.log 有几十个G。找到了!罪魁祸首就是它!
第三步:清理策略——删还是清空?
找到大日志文件后,不要急着 rm。
1. 较安全的做法:清空文件内容
如果你直接删除正在被程序(如Tomcat或Nginx)写入的日志文件,可能会导致文件句柄丢失,或者程序报错。 更稳妥的做法是清空文件:
Bash
# 将空内容重定向到日志文件中 echo "" > huge_log_file.log
这样做,文件大小瞬间变为0,且不需要重启服务。
2. 如果一定要删除
确认文件不再需要后,可以使用 rm 删除。但在删除 *.tar.gz 等备份文件时要小心。
隐藏关卡:为什么删了文件,空间却没释放?
这是很多新手的噩梦。 明明把 20G 的 access.log 删除了,再用 df -h 一看,磁盘占用率还是 95%!
原因:该文件正在被某个进程(比如 Nginx)打开。虽然你在文件系统中删除了文件名,但Linux内核认为该文件被进程占用,实际上并没有释放磁盘块。
解决办法:
- 查找“死而不僵”的文件:
Bash
# 查找已被删除但仍被进程占用的文件 lsof | grep deleted
- 如果提示
-bash: lsof: command not found,请先yum install lsof - 释放空间:
- 方法A(推荐): 重启占用该文件的服务(如
systemctl reload nginx)。重启后句柄释放,空间就回来了。 - 方法B(暴力): 根据 lsof 结果中的 PID,杀掉进程(
kill -9 PID)。
总结
遇到磁盘报警不要慌:
df -h看挂载点。du -h --max-depth=1 | sort -hr | head -n 10层层定位大文件夹。- 优先使用
echo "" > file清空日志。 - 删了没释放?用
lsof | grep deleted查进程并重启服务。