linux 根分区 / 可用空间很少了,但是 /home 下可用空间比较富余,如何优化?
- uvim管理员
你好!作为一名资深软件工程师,面对 Linux 系统根分区(
/)空间告急、而/home分区空间富余的情况,这可以说是运维和开发过程中非常经典且棘手的问题。根本原因通常是:初始分区时,把大部分空间分给了
/home(适合存用户个人文件),而存放系统文件、日志、容器镜像、数据库或应用缓存的/分区却分小了。针对这个问题,我有几种由浅入深、风险各异的解决方案供你选择。在操作前,请务必做好重要数据的备份(快照)。
方案一:清理与瘦身(治标,快速释放空间)
在动用分区调整这类大手术之前,先清理掉无用的垃圾,通常能救急。
1. 清理系统日志:
journald日志有时会占用几个G的空间。# 查看日志占用大小 journalctl --disk-usage # 清理保留最近 2 天的日志 sudo journalctl --vacuum-time=2d2. 清理包管理器缓存:
* Ubuntu/Debian:sudo apt clean sudo apt autoclean* CentOS/RHEL/Fedora:
sudo dnf clean all # 或 yum clean all3. 清理 Docker 缓存(如果你是开发者):
Docker 的镜像、容器和卷非常吃/var/lib/docker(默认在根分区)。# 清理所有未使用的容器、网络、镜像(未打标签的) sudo docker system prune -a --volumes4. 使用
ncdu查找大文件:
安装ncdu(Ncurses Disk Usage),直观地找出哪个目录最肥胖。sudo apt install ncdu # 或 yum install ncdu sudo ncdu /方案二:软链接迁移法(推荐,安全且改动小)
如果
/下面某个占用空间极大的目录(例如/var/lib/docker,/usr/local,/opt等)导致根分区爆满,我们可以把它整体搬到/home下,然后在原位置建立一个软链接(Symlink)。以迁移 Docker 目录(
/var/lib/docker)为例:1. 停止相关服务(防止迁移过程中数据写入损坏):
sudo systemctl stop docker2. 在
/home下创建目标目录:sudo mkdir -p /home/docker/lib3. 复制原目录数据到新位置(保留权限):
sudo rsync -aP /var/lib/docker/ /home/docker/lib/4. 备份原目录并创建软链接:
sudo mv /var/lib/docker /var/lib/docker.bak sudo ln -s /home/docker/lib /var/lib/docker5. 重启服务并验证:
sudo systemctl start docker确认一切正常运行后,可以安全删除
/var/lib/docker.bak释放空间。优点:不需要重新分区,风险低。
缺点:不适合所有目录(例如/bin,/sbin,/lib等系统启动必需的基础库不能随便外迁)。方案三:LVM 逻辑卷动态调整(最优雅,需 LVM 支持)
如果你的磁盘使用了 LVM(逻辑卷管理器),恭喜你,调整分区大小就像切蛋糕一样简单,不需要重新格式化。
你可以将
/home所在的逻辑卷空间“缩减”一部分,然后“腾出”给/所在的逻辑卷。前提条件:
/和/home必须在同一个卷组(Volume Group, VG)中。操作步骤:
1. 检查是否是 LVM:
df -Th # 查看文件系统类型,如果是 ext4/xfs,并且通过 lvs 或 vgdisplay 能看到卷组,说明支持。2. 卸载并缩减
/home空间(以 ext4 为例,假设要从/home抽调 20G):# 1. 确保没有进程占用 /home(最好进入单用户模式或通过 live CD 操作,线上的话确保无用户写入) sudo umount /home # 2. 检查文件系统完整性 sudo e2fsck -f /dev/mapper/vg0-home # 3. 缩减文件系统大小到目标大小(例如缩减到 50G) sudo resize2fs /dev/mapper/vg0-home 50G # 4. 缩减逻辑卷大小 sudo lvreduce -L 50G /dev/mapper/vg0-home # 5. 重新挂载 /home sudo mount /home3. 扩展
/根分区:# 1. 将释放出来的空闲空间加给根分区逻辑卷 sudo lvextend -l +100%FREE /dev/mapper/vg0-root # 2. 扩展文件系统 # 如果是 ext4: sudo resize2fs /dev/mapper/vg0-root # 如果是 xfs (CentOS 默认): sudo xfs_growfs /方案四:绑定挂载 Bind Mount(折中方案)
如果你不想做软链接,也可以使用
mount --bind技术。例如,把
/home/var_log挂载到/var/log。
在/etc/fstab中添加:/home/var_log /var/log none bind 0 0这样系统依然认为自己在写
/var/log,实际上数据全部落盘到了/home所在的富余空间里。总结建议
作为工程师,我的建议优先级是:
1. 先做方案一(清理日志和 Docker 缓存),往往能临时救急。
2. 如果是某个特定大目录(如 Docker、Maven 仓库、日志)撑爆了根,用 方案二(软链接),最快最稳。
3. 如果是标准的服务器架构且支持 LVM,果断用 方案三 从根本上解决问题。 在 Linux 系统中,
/tmp目录是用来存放临时文件的,系统重启时里面的很多内容通常会被清空,但有时会有一些失控的进程、崩溃转储(core dumps)或者大压缩包留在里面,导致占用大量根分区空间。作为资深软件工程师,我为你提供几种高效查看
/tmp目录下大文件的方法,你可以根据系统的具体工具选择使用。方法一:使用
du命令(最通用,无需安装额外工具)du(Disk Usage)是 Linux 自带的分析目录占用情况的神器。1. 查看
/tmp下一级目录或文件的大小并按大小排序:sudo du -h --max-depth=1 /tmp | sort -hr--max-depth=1:只查看/tmp下面第一层的文件或子目录。-h:以人类易读的格式显示(如 K, M, G)。sort -hr:按人类可读的数字大小进行降序排序(最大的排在最前面)。
2. 如果你想直接递归找出
/tmp下所有大于 100MB 的文件:sudo find /tmp -type f -size +100M -exec ls -lh {} +-type f:只找文件。-size +100M:找大于 100MB 的文件(你可以把 100M 改成 50M 或 1G)。-exec ls -lh {} +:把找到的文件用长格式详细列出来。
方法二:使用
ncdu(最直观,强烈推荐)如果你安装了
ncdu(前面清理篇提到过的小工具),这是查看磁盘占用体验最好的方式。如果没有安装,可以快速用sudo apt install ncdu或sudo yum install ncdu装一个。直接运行:
sudo ncdu /tmp* 特点:它会提供一个可视化的文本交互界面。你可以用上下箭头移动,按回车进入子目录,按
d可以直接删除选中的大文件(操作时请小心),按q退出。方法三:使用
ls命令组合(适合快速看一眼当前目录)如果你只想简单粗暴地按文件大小顺序列出
/tmp下的所有文件:sudo ls -lhS /tmp-S参数就是让ls直接按照文件大小降序排列。- 注意:这个命令只列出
/tmp根底下的文件,不会递归深入子目录。
💡 工程师小贴士(清理
/tmp的注意事项)1. 小心误删正在使用的临时文件:
有些正在运行的服务(如 MySQL、Java 应用、编辑器等)可能会在/tmp下写入 socket 文件或临时锁文件。直接盲目rm -rf /tmp/*可能会导致某些服务报错。2. 安全的清理方式:
如果确定要清理,建议只清理长时间未修改的临时文件(例如超过 7 天没动过的):sudo find /tmp -type f -mtime +7 -delete你可以先用方法一或方法二看看到底是哪个“罪魁祸首”占了空间,然后再决定是删除还是迁移。
要精准找出
/tmp目录下最大的前 10 个文件(排除目录,只针对具体文件),最有效且优雅的 Linux 命令组合如下:你可以直接复制并在终端中执行以下命令:
sudo find /tmp -type f -exec ls -lh {} + 2>/dev/null | sort -k5 -hr | head -n 10🔍 命令原理解析(资深工程师带你看懂):
1.
sudo find /tmp -type f:
* 在/tmp目录下寻找所有类型为文件(-type f)的目标。
* 使用sudo是为了防止有些临时文件权限属于 root 或其他用户,普通用户无法读取导致报错。2.
-exec ls -lh {} +:
* 将找到的所有文件传递给ls -lh,以人类可读的格式(如10G,500M)输出详细信息。3.
2>/dev/null:
* 把运行过程中可能产生的“权限拒绝(Permission denied)”等错误信息屏蔽掉,保持屏幕输出清爽。4.
sort -k5 -hr:
*sort是排序命令。
*-k5:指定按照ls输出结果中的第 5 列(即文件大小那一列,如4.2G、150M)进行排序。
*-hr:-h表示按照人类可读的单位(K/M/G)正确识别大小(不会把 2G 排在 10M 后面);-r表示逆序(Reverse),即从大到小排列。5.
head -n 10:
* 只取排序后的前 10 行,也就是我们最终需要的“最大的 10 个文件”。💡 进阶:如果你连“大目录”也想一起看呢?
有时候占用空间的不是单个大文件,而是一个塞满了小文件的庞大子目录。如果你想看
/tmp下占用空间最大的前 10 个对象(包括文件和子目录),可以使用下面这个du命令的组合:sudo du -h --max-depth=2 /tmp 2>/dev/null | sort -hr | head -n 10执行完这两个命令后,你大概率就能揪出罪魁祸首了。如果你看到了不认识的大文件,可以告诉我它的名字或后缀,我帮你分析它是哪个程序产生的、能否安全删除。
在 Linux 中,要查看某个目录下所有文件及子目录的大小,最常用的工具是
du(Disk Usage)。作为软件工程师,我为你准备了几个不同场景下的实用命令,你可以根据需要选择:
方法一:查看该目录下所有一级子目录和文件的大小(最常用)
如果你想知道某个目录(比如
/var/log)下面,每个子文件夹和文件各自占了多大空间:sudo du -h --max-depth=1 /path/to/dir- 参数解析:
-h:以人类可读的格式显示(如4.0K,25M,2.1G)。--max-depth=1:限制深度为 1。这意味着只列出该目录下一层的子目录和文件的大小(如果想看更深一层,可以把数字改成2)。/path/to/dir:替换为你实际想查看的目录路径。
方法二:查看目录下所有文件及子目录的大小,并【按从大到小排序】
仅仅列出来往往不够直观,我们通常需要找出最大的那个。配合
sort命令可以实现完美的排序:sudo du -h --max-depth=1 /path/to/dir | sort -hrsort -hr:-h:正确识别带有单位的大小(比如能分清10G比500M大)。-r:逆序(Reverse),让最大的排在最上面。
方法三:递归查看该目录下【所有】文件和子目录的大小(最全)
如果你不仅想看第一层,还想把该目录下所有深层的子目录、孙子目录、以及文件的具体大小全部列出来(慎用,如果文件很多会刷屏):
sudo du -h /path/to/dir | sort -hr去掉
--max-depth限制,du会递归遍历所有底层内容。💡 进阶:如果你想用图形化界面看
如果你是在有桌面环境的 Linux 上操作,或者通过 SSH 开启了 X11 转发,强烈建议使用
ncdu:sudo ncdu /path/to/dir它会弹出一个非常美观、支持交互的终端界面,自动按大小排序,你可以用方向键自由探索哪个目录最占地方。如果没装的话,用
sudo apt install ncdu(Ubuntu/Debian) 或sudo yum install ncdu(CentOS/RHEL) 即可快速安装。/var/log/nginx/目录占用空间过大,在生产环境中是非常常见的问题。这通常是因为 Nginx 的访问日志(access.log)或错误日志(error.log)体积失控,或者没有配置好日志轮转(Logrotate)。作为资深软件工程师,我为你提供一套从“紧急刹车(清理)”到“长治久安(配置优化)”的完整解决方案。
第一步:紧急瘦身(安全地清理现有大日志)
⚠️ 致命误区:千万不要直接
rm -rf access.log!
如果你直接删除了正在被 Nginx 写入的日志文件,Nginx 进程依然会把数据往那个已经不存在的句柄(inode)里写,导致磁盘空间不释放,同时还会一直占用内存。正确的做法是清空或者安全切割:
方案 A:直接清空日志文件(最快释放空间)
如果你暂时不需要这些历史日志,可以直接清空它们:
sudo truncate -s 0 /var/log/nginx/access.log sudo truncate -s 0 /var/log/nginx/error.log* 原理解析:
truncate -s 0会把文件大小截断为 0 字节,但文件依然存在,Nginx 可以继续正常写入,且空间立即释放。方案 B:平滑重启 Nginx(如果已经手动删错了)
如果你不小心用
rm删了日志,导致空间没释放,可以通过让 Nginx 重新加载配置文件来重置日志句柄:sudo nginx -s reopen第二步:治本之道——配置 Logrotate(日志轮转)
Linux 系统自带一个强大的日志管理工具叫
logrotate。它可以每天(或每周)自动把大日志打包、压缩、删除旧日志,防止日志无限变大。Nginx 通常在安装时会自动带一个 logrotate 配置文件。我们来看看它是怎么写的:
1. 检查配置文件:
通常位于/etc/logrotate.d/nginx。你可以用编辑器打开它:sudo cat /etc/logrotate.d/nginx它长这样:
/var/log/nginx/*.log { daily # 每天切割一次 missingok # 如果日志丢失,不报错继续 rotate 14 # 只保留最近 14 天的日志 compress # 压缩旧日志(变成 .gz,省空间) delaycompress # 延迟一天压缩(昨天切割的今天压缩,方便排查) notifempty # 如果日志是空的,不切割 create 0640 nginx adm # 切割后创建新日志文件的权限和属主 sharedscripts postrotate if [ -d /run/systemd/system ]; then systemctl kill -s USR1 nginx.service else kill -USR1 `cat /var/run/nginx.pid 2>/dev/null` fi endscript }2. 手动触发一次测试:
如果你刚修改了配置,想立刻测试日志轮转是否正常工作,可以运行:sudo logrotate -f /etc/logrotate.d/nginx执行后,去
/var/log/nginx/下看看是不是多出了带.1或.gz的压缩包,空间是否降下来了。第三步:Nginx 业务层面的优化(从源头减小日志体积)
如果你的网站访问量极大,日志每天几十个 G,光靠定时清理还不够,我们需要从 Nginx 配置上进行精简:
1. 关闭静态资源的访问日志
网站的图片、CSS、JS、ICO 等静态文件每天有大量的请求,记录它们的访问日志通常毫无意义(除非你在做 CDN 分析)。
在你的nginx.conf或对应域名的server块中加入:location ~* \.(jpg|jpeg|png|gif|ico|css|js|woff|woff2|ttf|svg)$ { access_log off; # 关闭这些文件的访问日志 expires max; # 同时开启客户端缓存 }2. 关闭健康的探活日志 (Health Check)
如果你用了 Kubernetes、SLB、或者 AWS ELB,它们会频繁请求
/health或/status接口来检查服务是否存活,这会产生大量无用日志。location = /health { access_log off; return 200 "healthy\n"; }3. 优化 Log Format(精简日志内容)
默认的
combined日志格式记录了很多可能用不到的信息。你可以自定义一个更精简的格式,或者只记录耗时较长、状态码非 200 的请求(例如只记录错误或慢请求):# 在 http 块中定义: log_format main_lite '$remote_addr - $remote_user [$time_local] "$request" ' '$status $body_bytes_sent'; # 在 server 块中使用: access_log /var/log/nginx/access.log main_lite;💡 总结与建议
1. 现在立刻做:用
sudo truncate -s 0 /var/log/nginx/*.log释放当前磁盘空间。
2. 检查自动化:确认系统的logrotate服务在正常运行(Ubuntu/CentOS 默认都有定时任务每天跑一次)。
3. 长远优化:在 Nginx 配置文件里把静态资源的access_log off加上,能直接帮你节省 50% 以上的日志空间。