Linux磁盘清理与扩容:从原理到实践
一、磁盘清理的基本原理1.1 磁盘空间是如何被消耗的Linux 文件系统的磁盘占用可归纳为以下几类1持久化数据操作系统文件/usr、/etc、/boot用户数据/home应用程序数据/var/lib下的数据库、容器存储等2缓存与临时数据包管理器缓存APT 的/var/cache/apt、Snap 的/var/lib/snapd容器运行时层Docker/containerd 的镜像层、快照层IDE 与开发工具缓存旧版本服务器文件、扩展缓存3日志数据系统日志systemd journal位于/var/log/journal应用日志Redis、Nginx、数据库等位于/var/log下各子目录日志轮转归档.1、.2、.gz等历史归档文件4交换空间交换分区或交换文件swap file用于内存扩展若未启用则纯属空间浪费1.2 清理的核心原则评估 → 定位 → 确认 → 清理 → 验证先评估后操作在删除任何文件前先全面了解磁盘空间分布先只读扫描再执行删除使用du、find等命令先查看确认无误后再删除保留当前在用版本清理 IDE 缓存、内核等时保留当前运行版本从安全区域开始先清理用户级数据低风险再清理系统级数据高风险验证清理效果清理后确认空间是否释放服务是否正常二、磁盘清理的重要性2.1 管理层面的影响磁盘使用率风险等级可能后果建议操作0% - 60%安全正常运行读写性能正常无需操作保持常规监控60% - 75%注意持续增长需关注潜在空间风险记录大文件分布规划清理周期75% - 90%警告写入性能下降部分操作可能失败执行du -sh /*定位大目录清理日志和容器缓存90% - 100%危险服务异常、系统崩溃风险高立即执行紧急清理考虑扩容或添加新磁盘2.2 典型场景容器化环境频繁拉取和删除容器镜像会导致 containerd 存储层堆积大量 orphaned 快照可轻松占用 10GB 空间日志累积未配置日志轮转的应用如 Redis 默认日志配置可在数月内产生数 GB 的日志文件开发环境IDE 的自动更新机制会保留多个旧版本服务器文件每个版本约 500MB - 1.2GB多个版本累加可达数 GB包管理器缓存长期未清理的 APT 和 Snap 缓存可占用数 GB 空间三、常见清理方法与工具介绍3.1 基础工具链工具用途常用参数df查看磁盘分区使用情况-h人类可读格式-T显示文件系统类型du统计目录/文件大小-sh汇总大小-a包含文件find查找文件-size按大小-atime按访问时间sort排序-rh逆序人类可读journalctl管理 systemd 日志--vacuum-size限制大小--vacuum-time限制时间3.2 容器清理工具# Docker 系统级清理命令dockersystem prune# 清理悬空资源dockersystem prune-a# 清理所有未使用镜像dockersystem prune-af--volumes# 最彻底清理含卷# 查看容器和镜像详情dockerps-a# 查看所有容器含已停止dockerimages# 查看所有镜像dockersystemdf-v# 查看磁盘使用详情3.3 日志清理工具与方法# 方法一systemd journal 日志管理journalctl --disk-usage# 查看当前日志大小sudojournalctl --vacuum-time7d# 保留最近 7 天sudojournalctl --vacuum-size200M# 限制总大小# 方法二截断日志文件不删除文件不影响运行中进程sudotruncate-s0/var/log/redis/redis-server.log# 方法三删除已轮转的旧日志sudofind/var/log-name*.gz-deletesudofind/var/log-name*.1-delete3.4 包管理器缓存清理# APTsudoaptclean# 清理所有下载的 .deb 包缓存sudoaptautoclean# 仅清理过时的包缓存sudoaptautoremove# 删除不再需要的依赖包# Snapsnap list--all|grepdisabled# 查看已禁用的旧版本sudosnap removepkg--revisionrev# 删除指定版本3.5 IDE 缓存清理# 确认当前运行版本psaux|grep-Etrae-cn-server|vscode-server|grep-vgrep# 查看 Trae IDE 旧版本通常位于 ~/.trae-cn-server/bin/du-sh~/.trae-cn-server/bin/*|sort-rh# 查看 VS Code 旧版本通常位于 ~/.vscode-server/cli/servers/du-sh~/.vscode-server/cli/servers/*|sort-rh# 删除 Trae IDE 旧版本保留当前运行版本rm-rf~/.trae-cn-server/bin/stable-*-debian10# 删除 VS Code 旧版本保留 lru.json 中第一个版本rm-rf~/.vscode-server/cli/servers/Stable-*四、案例实战分析以下案例基于一台实际运行的 Ubuntu 24.04 LTS 服务器该服务器同时运行 Docker 容器、Redis 服务并作为 Trae IDE 和 VS Code 的远程开发环境。4.1 问题表现管理人员收到磁盘告警检查发现$ df -h / 文件系统 容量 已用 可用 已用% 挂载点 /dev/sda2 49G 43G 3.8G 92% /核心指标磁盘使用率92%剩余可用空间仅 3.8GB系统处于危险状态存在服务异常风险4.2 原因诊断过程第一步全局扫描定位大目录sudodu-sh/*2/dev/null|sort-rh|head-10输出示例20G /var 9.7G /home 8.2G /snap 7.5G /usr 4.1G /swap.img 2.0G /data 136M /boot ...初步发现/var占用 20G最大/home占用 9.7G/swap.img占用 4.1G第二步下钻分析 /var 目录sudodu-sh/var/*2/dev/null|sort-rh|head-10输出示例18G /var/lib 1.2G /var/log 388M /var/cache ...发现/var/lib占 18G是核心问题所在。第三步深入分析 /var/libsudodu-sh/var/lib/*2/dev/null|sort-rh|head-10输出示例12G /var/lib/containerd 3.3G /var/lib/snapd 1.6G /var/lib/libvirt 817M /var/lib/docker 480M /var/lib/mysql 355M /var/lib/apt ...关键发现/var/lib/containerd占用12GB是最大的单一空间消耗源。第四步分析 Docker 容器与镜像dockerps-a输出示例CONTAINER ID IMAGE COMMAND STATUS NAMES d9a61ff3e12d 9a39b4 ./entrypoint.sh Exited (255) 5 hours ago jms_all 7e4913ecff49 3ddc97 docker-entrypoint.s… Exited (255) 5 hours ago jms_redis 5a12914af0b2 c83704 docker-entrypoint.s… Exited (255) 5 hours ago jms_mysqldockerimages输出示例REPOSITORY TAG SIZE registry.aliyuncs.com/openspug/spug latest 1.05GB registry.cn-beijing.aliyuncs.com/jms_all v4.10.15 ~1.2GB registry.cn-beijing.aliyuncs.com/redis 7.2.5 ~500MB registry.cn-beijing.aliyuncs.com/mariadb 10.6 ~500MB ...发现存在多个已退出的 JumpServer 相关容器以及大量已拉取的镜像这些镜像的存储层被 containerd 缓存。第五步分析日志文件sudodu-sh/var/log/redis/*.log输出示例447M /var/log/redis/redis-server.log 418M /var/log/redis/redis-server.log.1sudojournalctl --disk-usage输出示例Archived and active journals take up 256.4M发现Redis 日志文件累计约865MBsystemd journal 约256MB。第六步分析用户目录sudodu-sh/home/xxx/* /home/xxx/.*2/dev/null|sort-rh|head-10输出示例5.9G /home/xxx/.trae-cn-server 3.3G /home/xxx/.vscode-server ...发现IDE 缓存占用约9.2GB其中 Trae IDE 有 5 个旧版本每个约 1.2GBVS Code 有 5 个旧版本每个约 480-540MB。第七步检查 swap 文件swapon--show输出示例无输出free-h输出示例total used free 内存 7.2Gi 2.6Gi 1.3Gi 交换 0B 0B 0Bgrepswap /etc/fstab输出示例#/swap.img none swap sw 0 0发现/swap.img占用 4.1GB但已在/etc/fstab中被注释完全未启用。诊断总结问题大小占比根因containerd 残留层12.0 GB27.9%旧容器镜像层未被清理IDE 旧版本缓存9.2 GB21.4%自动更新累积多个版本未启用的 swap 文件4.1 GB9.5%配置变更后未清理日志文件累积1.1 GB2.6%日志轮转策略缺失其他16.6 GB38.6%系统文件、Snap 等总可回收空间约 26.4 GB4.3 解决方案实施步骤阶段一日志清理安全快速见效# 1. 截断 Redis 主日志447MBsudotruncate-s0/var/log/redis/redis-server.log# 2. 删除已轮转的 Redis 旧日志418MBsudorm-f/var/log/redis/redis-server.log.1# 3. 压缩 systemd journal 到 7 天216MB → 40MBsudojournalctl --vacuum-time7d# 4. 清理其他轮转日志sudorm-f/var/log/syslog.*.gz /var/log/syslog.* /var/log/kern.log.* /var/log/auth.log.*阶段一小计释放约1.1 GB阶段二容器与运行时清理回收最大空间# 1. 删除已退出的 JumpServer 容器dockerrm-fjms_all jms_redis jms_mysql# 2. 删除 JumpServer 相关镜像dockerrmi registry.cn-beijing.aliyuncs.com/wangxiaochun/jms_all:v4.10.15dockerrmi registry.cn-beijing.aliyuncs.com/wangxiaochun/redis:7.2.5dockerrmi registry.cn-beijing.aliyuncs.com/wangxiaochun/mariadb:10.6# 3. 彻底清理 Docker 所有未使用资源含卷dockersystem prune-af--volumes执行效果docker system prune -af --volumes不仅清理了 Docker 层面的资源还回收了 containerd 中 orphaned 的 content 数据content 从 2.8GB 降至 36KBoverlayfs 从 8.3GB 降至 3.4GB。总回收8.28 GB38 个镜像层被删除含多个 jumpserver 镜像、postgres、nginx、redis、hello-world 等阶段二小计释放约8.3 GB阶段三IDE 缓存清理保留当前版本# 1. 确认当前运行的 Trae IDE 版本psaux|greptrae-cn-server|grep-vgrep# 输出显示当前使用: stable-ee4fa801...-debian10# 2. 保留当前版本删除其余 4 个旧版本每个 ~1.2GBrm-rf~/.trae-cn-server/bin/stable-f04583566a62dc47fac1d85d95480988f16bf6c5-debian10rm-rf~/.trae-cn-server/bin/stable-2a65c0302f073ab6bd84db06c2a21ae3252cbd16-debian10rm-rf~/.trae-cn-server/bin/stable-86028a8cd52d10a7e5964875157e67ad1509289c-debian10rm-rf~/.trae-cn-server/bin/stable-d9ad807cd897ef11c83d5b5e3c2a52b63845efe7-debian10# 3. 确认当前运行的 VS Code 版本LRU 中第一个为最新cat~/.vscode-server/cli/servers/lru.json# 输出: [Stable-7e7950..., Stable-fcf604..., ...]# 4. 保留最新版本删除其余 4 个旧版本每个 ~480-540MBrm-rf~/.vscode-server/cli/servers/Stable-fcf604774b9f2674b473065736ee75077e256353rm-rf~/.vscode-server/cli/servers/Stable-6928394f91b684055b873eecb8bc281365131f1crm-rf~/.vscode-server/cli/servers/Stable-ffa3c3f656c8df32d894e5f4d3673284d424205erm-rf~/.vscode-server/cli/servers/Stable-6a44c352bd24569c417e530095901b649960f9f8阶段三小计释放约6.8 GB阶段四删除未使用的交换文件# 确认 swap 未启用后直接删除sudorm-f/swap.img阶段四小计释放约4.1 GB4.4 清理后效果评估磁盘空间对比指标清理前清理后变化已用空间43 GB22 GB-21 GB可用空间3.8 GB26 GB22 GB使用率92%47%-45%各目录变化明细目录清理前清理后变化/var/lib/containerd12.0 GB3.4 GB-8.6 GB.trae-cn-server/bin5.5 GB1.2 GB-4.3 GB.vscode-server/servers2.5 GB540 MB-2.0 GB/swap.img4.1 GB0 B-4.1 GB/var/log/redis865 MB微量-865 MB/var/log/journal256 MB40 MB-216 MB服务健康状态清理后确认所有关键服务正常运行dockerps# 容器运行正常systemctl status redis# Redis 服务正常psaux|greptrae-cn-server# Trae IDE 连接正常五、分类清理策略总结5.1 按风险等级分类风险等级清理对象典型操作建议频率低风险APT 缓存、临时文件apt clean,find /tmp每周低风险已轮转的旧日志find ... -name *.gz -delete每月中风险Systemd journaljournalctl --vacuum-time7d每月中风险IDE 旧版本缓存保留最新版删除其余每季度中风险已停止的容器、悬空镜像docker system prune每月高风险未使用的镜像全部docker system prune -a按需高风险数据卷docker system prune --volumes按需谨慎高风险未使用的 swap 文件sudo rm -f /swap.img一次性5.2 按场景选择策略日常维护每周耗时 5 分钟sudoaptcleansudojournalctl --vacuum-time7ddockersystem prune-f空间不足应急按需耗时 15 分钟# 1. 快速定位大目录sudodu-sh/*2/dev/null|sort-rh|head-10# 2. 清理 Docker 未使用资源含卷dockersystem prune-af--volumes# 3. 截断大日志文件sudofind/var/log-name*.log-size100M-exectruncate-s0{}\;# 4. 清理 systemd journalsudojournalctl --vacuum-size200M# 5. 清理 IDE 旧版本缓存rm-rf~/.trae-cn-server/bin/*/stable-*2/dev/null# 保留当前版本前需确认rm-rf~/.vscode-server/cli/servers/Stable-*2/dev/null# 保留当前版本前需确认定期深度清理每月耗时 30 分钟# 完整清理流程包含所有步骤dockersystem prune-af--volumes# 清理容器、镜像、卷sudojournalctl --vacuum-size200M# 限制 journal 日志大小# 清理 IDE 旧版本保留当前运行版本rm-rf~/.trae-cn-server/bin/stable-*-debian10# 逐一确认后删除勿删当前版本rm-rf~/.vscode-server/cli/servers/Stable-*# 保留 lru.json 中第一个版本# 清理 Snap 旧版本snap list--all|grepdisabled|awk{print $1, $3}|whileread-rpkgrev;dosudosnap remove$pkg--revision$rev;done六、预防性措施与最佳实践6.1 配置日志轮转# 限制 journald 日志大小sudotee/etc/systemd/journald.conf.d/limit.confEOF [Journal] SystemMaxUse200M MaxFileSec7day EOFsudosystemctl restart systemd-journald# 配置应用日志轮转以 Redis 为例sudotee/etc/logrotate.d/redisEOF /var/log/redis/*.log { weekly rotate 4 compress delaycompress missingok notifempty postrotate /bin/systemctl reload redis-server /dev/null 21 || true endscript } EOF6.2 建立监控告警# 简单脚本磁盘使用率超过 80% 时发送告警#!/bin/bashTHRESHOLD80USAGE$(df-h/|awkNR2 {print $5}|tr-d%)if[$USAGE-gt$THRESHOLD];thenechoWARNING: Disk usage at${USAGE}% on$(hostname)|mail-sDisk Alertadminexample.comfi6.3 容器镜像管理策略使用docker system prune -f作为定时任务cron按需执行拉取镜像前评估必要性避免拉取后不使用使用docker image ls --digests追踪镜像来源定期审查运行的容器清理不再使用的服务七、结语磁盘清理不是一次性的救火行为而是系统生命周期管理中的常态化工作。本文通过案例实践展示了从问题发现、根因诊断、方案实施到效果评估的完整闭环。核心要点如下先诊断后清理使用du、df、find等工具全面评估避免盲目操作分层清理由低风险到高风险从日志、缓存等安全区域开始再到容器、swap 等高风险区域保留当前版本清理 IDE 缓存、内核等时确认当前运行版本并保留验证效果清理后通过df -h、docker system df等命令验证空间释放情况并确认服务正常建立长效机制配置日志轮转、设置监控告警、制定定期清理计划防患于未然在本次案例中通过系统化的清理操作磁盘使用率从92% 降至 47%释放约21GB空间使系统恢复正常运行状态。这一过程充分说明科学的磁盘清理方法能够在短时间内显著改善系统健康状况是每个 Linux 管理人员和管理员应掌握的核心技能。八、磁盘扩容案例环境/dev/sda磁盘 80G原/dev/sda2分区 50G存在 30G 未分配空间需在线扩容。8.1 前置检查查看磁盘分区布局lsblk输出示例sda 8:0 0 80G 0 disk ├─sda1 8:1 0 1M 0 part └─sda2 8:2 0 50G 0 part /关键信息磁盘总大小、分区编号、各分区大小、挂载点。确认未分配空间sudofdisk-l/dev/sda关注最后一个分区的结束扇区与磁盘总扇区数的差值差值即为未分配空间。确认文件系统类型df-hT/输出示例文件系统 类型 容量 已用 可用 已用% 挂载点 /dev/sda2 ext4 49G 22G 25G 47% /ext4使用resize2fs在线扩容xfs使用xfs_growfs在线扩容8.2 扩容步骤扩展分区使用growpart命令将分区扩展到磁盘末尾sudogrowpart /dev/sda2参数说明/dev/sda为磁盘设备2为分区号中间有空格。成功输出CHANGED: partition2 start4096 old: size104851456 end104855551 new: size167768031 end167772126若growpart不可用安装sudo apt install cloud-guest-utils扩展文件系统# ext4 文件系统sudoresize2fs /dev/sda2# 若为 xfs 文件系统使用# sudo xfs_growfs /成功输出/dev/sda2 上的文件系统已被挂载于 /需要进行在线调整大小 old_desc_blocks 7, new_desc_blocks 10 /dev/sda2 上的文件系统大小已经调整为 20971003 个块每块 4k。验证扩容结果df-hT/ lsblk /dev/sda8.3 扩容前后对比指标扩容前扩容后分区大小50G80G文件系统大小49G79G已用22G22G不变可用25G54G使用率47%29%8.4 注意事项注意事项说明无需重启growpartresize2fs均支持在线操作不中断服务文件系统支持ext4 使用resize2fsxfs 使用xfs_growfs两者均支持在线扩容分区表格式本例为 MBR 分区表fdiskGPT 分区表需使用gdisk或parted备份建议操作前建议备份重要数据尤其是生产环境扩容方向未分配空间必须在目标分区之后磁盘末尾否则无法直接扩容8.5 常见问题Q1growpart报错 “unexpected output”原因分区表被占用。确保没有进程正在使用该分区或先卸载不适用于根分区。Q2根分区无法卸载根分区不支持卸载扩容growpartresize2fs的在线扩容方案是唯一选择。Q3如何确认扩容成功# 查看分区大小是否接近磁盘总大小sudofdisk-l/dev/sda|grepsda2# 查看文件系统大小是否接近分区大小df-h/Q4扩容后文件系统大小未更新确保先执行growpart扩展分区再执行resize2fs扩展文件系统顺序不可颠倒。8.6 参考命令速查# 查看磁盘布局lsblk# 查看分区表sudofdisk-l/dev/sda# 扩展分区需要未分配空间在分区之后sudogrowpart /dev/sda分区号# 扩展 ext4 文件系统sudoresize2fs /dev/sda分区号# 扩展 xfs 文件系统sudoxfs_growfs挂载点# 验证df-hT/ lsblk九、创建新分区与挂载磁盘当系统添加了新磁盘或需要将剩余未分配空间创建为一个独立分区时可以按照以下步骤操作。9.1 查看磁盘状态df-h9.2 查看已存在分区sudofdisk-l9.3 创建新分区使用fdisk工具对磁盘进行分区sudofdisk/dev/sda在fdisk交互界面中依次执行输入n创建新分区选择分区类型主分区 Primary / 扩展分区 Extended选择分区编号设置起始和结束扇区使用默认值可占用全部可用空间输入w保存更改并退出9.4 更新分区表sudopartprobe /dev/sda不执行分区表更新可能导致新分区无法格式化。9.5 格式化分区sudomkfs.ext4 /dev/sda39.6 挂载分区创建目标挂载点并挂载sudomkdir-p/datasudomount/dev/sda3 /data9.7 持久挂载配置为了在系统重启后保持挂载状态需要将分区添加到/etc/fstab文件中echo/dev/sda3 /data ext4 defaults 0 0|sudotee-a/etc/fstab9.8 验证挂载结果df-h9.9 常用分区命令速查命令用途示例fdisk -l查看分区表sudo fdisk -l /dev/sdapartprobe通知内核分区表变更sudo partprobe /dev/sdamkfs.ext4格式化为 ext4sudo mkfs.ext4 /dev/sda3mount挂载分区sudo mount /dev/sda3 /dataumount卸载分区sudo umount /datablkid查看分区 UUIDsudo blkid /dev/sda3