ARTICLE DETAIL

资讯详情

深耕网站建设、视觉设计与SEO优化的一线实战洞察。

Ubuntu磁盘清洁实战:从apt缓存到journald日志

Ubuntu磁盘清洁实战:从apt缓存到journald日志

我习惯把 Ubuntu 桌面和服务器都当生产工具用,时间一长,那块根分区就会莫名其妙地变满,明明装的东西不多,df -h一查却红了。有次我负责的一台测试机就是因为/被日志和 apt 缓存塞满,服务直接异常退出,排查了半天才发现是磁盘没空间了。从那以后,我养成了一个习惯:定期给系统做清理,把“不需要的文件”认认真真清一遍。这篇文章就是把我在 Ubuntu 上常用的清理思路、具体命令和踩过的坑整理出来,覆盖包管理器缓存、日志、临时文件、孤儿依赖这些最常见的占用来源。不管是跑在服务器上的精简版,还是装了全家桶的桌面版,这套方法基本都能用,新手照着做不会删错东西,老手也能看看有没有漏掉什么死角。

1. 清理前的“体检”:先搞清楚文件都占在哪

清理系统最忌讳的就是上来就删,连空间被谁吃了都不知道。我见过有人直接rm -rf /var/xxx,结果删错目录导致服务起不来,得重装系统。所以在动手之前,先花两分钟做个体检,搞清楚哪些目录权重最大,再针对性清理,效率会高很多,也安全得多。

1.1 用磁盘占用命令摸清底细

最基础的两个命令是df和du。df -h看的是整个分区的使用情况,能快速定位哪个挂载点快满了,比如根分区/、/home、/boot这些。du -h --max-depth=1 /则是从根目录往下逐层看每个目录占了多少,这样能直观地看出/var、/usr、/home到底谁是“大头”。不过要注意,du扫描全盘会比较慢,尤其在机械硬盘上,我通常直接用ncdu这个交互式工具替代,界面是命令行 TUI,能像文件管理器一样一层层钻进目录看大小,排序也清楚,比盲打du方便太多。如果机器上没装,一条sudo apt install ncdu就行,单文件绿色工具,不会引入额外依赖。

有个小细节要提醒:du默认统计的是当前目录下的所有内容,如果文件是 root 权限的,普通用户跑du有些目录会无权访问,建议直接sudo ncdu /,一步到位,避免那些“明明看着小,实际清理权限要 root”的尴尬情况。

1.2 区分“能删的”和“不能碰的”

体检完了你会看到一堆目录,这时候最怕的是分不清哪些是系统运行必需的。我给自己定了一个简单规则:/usr和/opt这类软件目录基本不手动删,里面的东西交给包管理器去处理;/home下自己用户目录内的缓存可以大胆清;/var目录要区别对待,日志和包缓存能清,但数据库、容器数据目录绝对不能乱动;/boot里就是内核文件,要留最新的一两个版本,其他老的交给apt自动清理。记住一个原则:凡是包管理器安装的东西,卸载或清理都优先用包管理器,自己手动删文件很容易让软件处于“半删除”状态,后面升级都成问题。

关于/var我单独多说一句:很多人看/var/lib/docker占用巨大,就直接删里面的文件,这种做法非常危险。正确的做法是用docker system prune去清理悬空镜像和停止的容器,而不是手动删目录。我见过一台机器因为手工删了 docker 的 overlay2 目录,容器全挂了,数据也丢了。所以清理工作最重要的一步不是跑命令,而是先有敬畏心。

2. 包管理器留下的垃圾:从缓存到孤立依赖

Ubuntu 底层用的是 APT 体系,日常安装卸载软件都会绕不开它。APT 有一个容易被忽略的特点:它会把下载过的.deb安装包缓存在/var/cache/apt/archives里,时间一长,这个目录能积累几个 GB 的垃圾。再加上无用的依赖包、旧内核,这些是清理的大头,也是最容易出问题的地方。

2.1 apt 缓存、孤立依赖与旧内核清理

很多人不知道 apt 下载的安装包会留在本地。每次apt install一个软件,对应的.deb包就被存在/var/cache/apt/archives/,装完之后并不自动删除。如果你经常装软件、升级系统,这个缓存目录会持续膨胀,有的机器上能占到 2GB 以上。清掉它很简单:

sudo apt clean

这条命令会把archives目录下的所有.deb文件清空,之后再安装软件时如果下载中断,就需要重新下载,但在正常网络条件下这没有任何副作用。如果不想全部清空,只想删掉之前版本残留的包,用sudo apt autoclean,它只清理那些已经无法再下载的旧版本包文件,比clean温和一点。

第二个重点是孤立依赖。装过软件的都知道,apt install某个软件时,会把它依赖的公共库一起装进来。当你用apt remove删掉那个软件时,那些库并不会自动移除,因为系统不知道它是否还被其他软件引用,于是一次次地装完卸、卸完装,系统里就会囤积越来越多“哪怕不再被使用”的依赖包。清理它们的命令是:

sudo apt autoremove

这个命令会把那些“已经不再被任何已安装软件所依赖”的包自动找出来并删除,是最安全、收益最直接的清理动作。执行后终端会列出即将移除的包列表,记得扫一眼,看看是不是真的都是无用的库或旧内核,确认没问题再继续。

第三个重点是旧内核。Ubuntu 升级后不会自动移除旧内核,启动引导界面会越积越多,/boot空间告急。手动清理内核有风险,建议用apt的方式:

sudo apt --purge autoremove

--purge参数会在删除包的同时把配置文件也一并清掉,避免残留杂七杂八的配置。这个命令会把不再被需要的内核镜像(如linux-image-*)和头文件(如linux-headers-*)一并清理,并自动更新 GRUB 引导配置,只保留最新版本和当前正在运行的内核,非常省心。

2.2 检测哪些依赖“该被记恨”:自动安装标记

如果你用惯了snap和flatpak,apt 的 autoremove 只能清掉它自己那套体系里的依赖,snap、flatpak 的旧版本残留不归它管。snap 默认会保留几个历史版本,时间一长,snapd的缓存和旧版本也会吃空间。手动查一下当前系统 snap 包占了多少空间:

du -h /var/lib/snapd | sort -h | tail -5

如果发现 snap 的体积很大,可以用snap list查看哪些包有旧版本,然后只保留所需的核心里面那条,用sudo snap remove把用不上的版本和包删掉。flatpak 同理,flatpak uninstall --unused会清掉不再被引用的运行时和依赖。

这里有个关键概念“自动安装标记”:你在apt install时手动指定的包会被标记为“手动安装”(manual),而被作为依赖自动拉进来的包则标记为“自动安装”(auto)。autoremove只会清理处于“自动安装”状态且当前没有其他包依赖它的那些。要看哪些包是自动装的,可以用apt-mark showauto,想看手动装的就用apt-mark showmanual。如果你觉得某个包虽然被自动拉进来,但你其实还要长期使用,可以改成手动安装标记,防止以后被 autoremove 误删:

sudo apt-mark manual 某个软件包名

这个操作很多人一辈子用不上,但一旦某天你发现某个库被autoremove波及了,再用它去恢复标记也不迟。

3. 日志和缓存的瘦身:journald 与用户缓存

很多人的根分区被塞满,背后的“真凶”其实是系统日志。Ubuntu 从 15.04 开始引入 systemd 之后,日志不再是一堆散落在/var/log下的文本文件,而是统一由 journald 管理,存放在/var/log/journal目录。如果不去限制它的体积,它会把你的磁盘悄悄吃掉一半。

3.1 journald 日志的限制与清空

journald 的默认配置不设上限,它会一直保留日志,直到磁盘满才算事。首先像这样先看看自己系统上这个问题有多严重:

journalctl --disk-usage

结果会直接显示当前日志占用的磁盘空间,我在一些跑了一年多的机器上见过日志直接吃掉 5 到 10GB 的。为了让日志不再疯长,建议直接修改/etc/systemd/journald.conf,找到SystemMaxUse这个配置项,改成类似500M这样的值,意思是日志最多占用 500MB,到达上限后,系统会自动用新的日志覆盖最旧的日志,不再需要手动去管。

改完配置后执行sudo systemctl restart systemd-journald重启生效。对于已经堆积的日志,最直接的办法是让它瘦身:

sudo journalctl --vacuum-size=400M sudo journalctl --vacuum-time=7d

这两条命令分别是“把日志总大小压缩到 400MB 以内”和“只保留最近 7 天的日志”,二选一即可,执行后 journald 会主动删除超出的部分。注意它只删 journald 管的日志,/var/log/syslog这类文本日志文件是另一个体系,通常只需关注那几个大文件,比如syslog、kern.log,它们如果没被 logrotate 轮转,可以手动清空:

sudo truncate -s 0 /var/log/syslog

用truncate而不是rm,是为了保留文件本身和权限,因为你正在跑服务可能还开着这个文件的句柄,直接删掉会导致服务静默地往已删除的 inode 继续写,磁盘空间反而释放不出来。

3.2 用户目录下的缓存、缩略图与旧配置文件

用户主目录下的缓存也是不容忽视的一块。先看一个地方:ls ~/.cache目录,里面有浏览器缓存、软件运行时的临时缓存等,可以直接整体清掉:

rm -rf ~/.cache/*

这条命令只会影响当前用户的缓存,系统软件不受影响,碰到正在运行的软件,它会重新生成缓存,稍慢一点而已。还有些遗留的临时文件躲在/tmp和/var/tmp,系统重启会自动清空/tmp,但/var/tmp会保留,里面可能有些旧文件,按需手动清理即可。

再说一个很容易被忽略的细节:桌面版的 Ubuntu 会在你浏览一大堆图片后,在~/.cache/thumbnails里生成缩略图缓存,积少成多也是一两 GB,同样可以清掉。另外,~/.bash_history这类 shell 历史文件、~/.local/share/Trash回收站,以及那些卸载软件后残留在~/.config或~/.local/share里的旧配置目录,这些文件往往已经在磁盘上躺了几个月甚至几年,如果软件早就不用了,大胆地删掉。

如果系统里装了中文输入法或各种跨端软件,~/.local/share底下可能还有一堆应用数据残留。我的做法是:每季度做一次用户目录大扫除,把不用的软件配置连同缓存一起清掉,每次都能释放出相当可观的空间。

4. 大文件与重复文件排查:定位“磁盘杀手”

上面几类清理都做完了,空间如果还是不够,那就说明系统里可能存在一些隐蔽的大文件,比如误放的大型压缩包、模型文件、日志,或者不同目录下的重复文件。这时候需要从文件本身入手,一个一个揪出来。

4.1 定位大目录、大文件的实用工具

定位大目录我用ncdu已经讲过了,但在排查“具体某个文件”时,用find更直接:

find / -xdev -type f -size +500M 2>/dev/null

-xdev表示只在当前文件系统内查找,这样就不会扫描到/proc、/sys这类虚拟目录,也跳过网络存储等挂载点。2>/dev/null是屏蔽掉无权限访问目录的报错信息。跑完你就知道哪些文件是大头,比如有些下载工具会因为断点续传留下.part文件、有些人会把日志从容器里导出来放在根目录,这些一眼就能认出是不是该删掉的。

想要图形化一点的话,du配合sort也能快速找出当前目录下最大的几个文件:

du -ah /home/某用户名 | sort -rh | head -20

这条命令会递归统计/home/某用户名下所有文件的大小,按大到小排序,取前 20 个。我自己是习惯先跑一条这样的命令,再决定要不要用 ncdu 交互式看细节,双管齐下,效率很高。

4.2 重复文件的识别与清理

重复文件也是值得留意的一块。尤其是做开发或者搞设计的人,习惯性“复制一份备份”,结果同个 ISO 镜像、同个模型文件、同个数据集在不同目录里存了三四份。手工对比文件名看不出什么,得用fdupes这类工具按内容去重:

sudo apt install fdupes fdupes -r /home/某用户名

它会扫描给定目录里所有文件,按内容计算出哈希值做对比,找出完全相同的文件组。加-d参数可以交互式地保留其中一份、删除其余副本,但我的建议是先用只扫描的模式看看有哪些重复,自己判断一下那些该删,尤其要注意有些应用(比如数据库、Git 仓库)内部会设计冗余文件,不同目录下的同名同内容很可能是正常状态,不要一刀切。

重复文件还有一个隐蔽场景是~/.local/share/Trash回收站和备份工具的快照目录,系统里可能有软链接这种形式指向同一份数据,用ncdu看空间时它只算一次,但用fdupes扫描时都是重复项,清理前一定看清楚是普通文件还是链接。

5. 让清理自动化:定时任务与日常维护习惯

手动清理始终不是长久之计。很多人问我为什么明明清干净了,过两个月又满了,其实是因为系统里的缓存、日志和软件更新每时每刻都在产生新文件,光靠“想起来才清一次”根本没法和增量抗衡。从我自己踩过的坑来看,做好自动化之后,人工清理的压力会小很多。

5.1 配置定时清理 journald 和日志轮转

journald 的SystemMaxUse配置属于“上限守护”,只要你设置好,它就不会超过那个阈值,这算是自动化第一步。但系统里其他日志,比如 Nginx、MySQL、K8s 组件写出来的日志,得靠 logrotate 来轮转。Ubuntu 默认装了/etc/logrotate.d/里的一套规则,但不同软件不一定自带,可以自建规则。

/etc/logrotate.d/里建一个文件(比如命名为myapp),内容可以这样写:

/var/log/某应用/*.log { daily rotate 7 compress delaycompress missingok notifempty copytruncate }

一行行拆开来说:daily是每天轮转一次,rotate 7是保留最近 7 份轮转后的日志,更早的就删掉,compress是轮转后立即用 gzip 压缩,delaycompress是只压缩当前轮转出的新文件,不管正在写的那个,missingok是文件不存在也没关系,不报错,notifempty是空文件不轮转,copytruncate适合应用不响应日志重开的场景,直接复制一份并把原文件截断,避免进程还握着旧文件句柄继续写。

设置好之后,系统会自动触发 logrotate,日积月累能省下大量磁盘空间,而且日志仍然保留一段时间的回溯能力,排查问题不耽误。

5.2 用 systemd timer 定期执行清理脚本

cron 是传统方案,但我更推荐 systemd timer,因为 Ubuntu 对 systemd 的集成度极高,用 systemd timer 跑清理任务,启动依赖、运行时机、失败重试都能统一管理。比如写一个清理脚本放在/usr/local/bin/system-clean.sh:

#!/bin/bash apt clean apt autoremove -y journalctl --vacuum-time=7d > /dev/null 2>&1

给脚本加上可执行权限之后,创建一个 service 和一个 timer 文件。service 负责定义“做什么”,timer 负责定义“什么时候做”。在/etc/systemd/system/下创建system-clean.service和system-clean.timer这两个文件,前者的内容指向刚写的脚本路径,后者的OnCalendar=weekly表示每周执行一次,也可以写成OnCalendar=*-*-* 04:00:00这种精确到凌晨四点的形式。然后执行sudo systemctl daemon-reload和sudo systemctl enable --now system-clean.timer即可启用。

这种方式的优势在于可审计、可维护,普通用户完全能够照着设置。如果不想碰 systemd,也可以直接在 crontab 里写一行0 3 * * 7 /usr/local/bin/system-clean.sh,但说实话,systemd timer 在排错、看日志的体验上比 cron 强太多。

5.3 我的日常维护习惯

最后分享一个维护习惯:每次系统大版本升级(比如从 22.04 升到 24.04)前后,我会专门留出一段时间做“清理 + 备份 + 升级”。清理就是上面这一整套流程,备份是用rsync把重要的配置目录和项目数据拷走,升级用的是do-release-upgrade。这样流程固定下来之后,系统理论上会越来越健壮,而不是越用越卡、越用越满。对我来说,自动化清理的意义不是“一劳永逸”,而是把原本需要人工介入的事情变得可预期,一旦出问题,翻日志就能看到什么时候跑的、输出了什么,一切清清楚楚。

6. 清理后的验证与常见问题排查实录

清理不是终点,验证才是。清完就跑,不确认一下结果,后面出问题时你都不知道是不是清理阶段埋的雷。我的习惯是每一步清理后对比一下前后磁盘空间的变化,最后再统一做一次验证,顺便看看有没有清理过程中留下的隐患。

6.1 清理成果怎么验收

最直观的验收方式还是df -h,看看/、/home、/boot这几个关键分区使用率降了多少。更细一点可以用ncdu /再看一遍目录结构,确认想要的目录确实瘦下去了。如果想看系统层面的整体健康度,systemd-analyze能查看服务启动时间等指标,但这些不是清理必须的。

如果清理过程中改过 journald 配置,建议重启一下服务并确认日志功能正常:journalctl -n 20能看到最近几条日志,说明 journald 依然正常工作。如果是 apt 相关操作,可以顺手跑一下sudo apt update,确保清理没有误伤软件源信息。

6.2 常见清理问题速查

我把实际遇到过的典型问题整理成了一个速查表,方便大家按图索骥:

问题现象可能原因解决办法
apt autoremove提示“下列软件包将被删除”包含自己认识的软件依赖被误标记为自动安装先取消自动标记:sudo apt-mark manual 包名,再执行 autoremove
清理 journald 后日志文件仍然显示占用很大有服务还占用旧日志文件句柄重启对应服务,或sudo systemctl restart systemd-journald
误删了某个库,软件启动报error while loading shared libraries某个软件依赖被删用sudo apt install装回对应库,或重新安装该软件
df -h显示空间已释放,但du结果与实际不符删除文件还被进程占用用lsof +L1 2>/dev/null查看已删除但仍被占用文件,重启相关进程
/var/cache/apt/archives清理后空间没减少有进程占用 apt 锁或目录检查是否有 apt 任务运行,稍后再试

lsof +L1这个命令值得多说两句。它列出的是 inode 已被删除、但文件仍有进程持有的场景,在清理日志时特别常见。比如你truncate了日志文件,但应用一直没重开文件句柄,磁盘空间不会被内核释放,原因就是文件被占用。解决办法一般是systemctl restart 对应服务,或者直接重启机器,不要强制 kill 进程以免造成数据损坏。

6.3 别犯的删除错误

说了这么多安全的清理方式,也得提醒哪些是新手最容易犯的删除错误。rm -rf /usr、rm -rf /var、rm -rf /lib这种“想把库清一遍”的思路千万不要有,系统会直接报废;sudo apt remove python3会把一堆依赖它的核心组件全部带走,Ubuntu 桌面环境都依赖 Python,删了等于自毁;find / -name “*.log” -delete这种想着把所有日志一次性删掉的做法做得太粗暴,很多软件正在写的日志被你删了,进程不会自动重建文件,只能等到重启才恢复。这些错误的共同点是“越过了包管理器、越过了系统设计,自己去硬删核心目录”,结果往往比不清理还糟。

清理完文件之后,如果不是特别急需空间,我会再花几分钟跑一遍sudo updatedb(如果装了 mlocate/locate)把文件索引刷新一版,避免后面用locate找文件时列出一堆早已不存在的路径去误导自己。

7. 从清文件到清习惯:一些个人经验收尾

清理 Ubuntu 做了这么多次,我最大的体会是:真正省心不是靠某个“一键清理”的命令,而是靠一套能嵌入日常使用的习惯和约束。比如我装新软件前会先看一眼它的依赖,是 apt 还是 snap 还是 flatpak,心里有数;尽量定期升级而不是攒到大版本才动;日志和缓存这类只增不减的东西,都是从一开始就限好上限,而不是等占满了再想办法。

还有一点比较实际的经验是:每次清理时,最好先开一个终端窗口,把要执行的命令一条条跑,每执行一步都看一眼输出,确认它要删除的东西确实“不需要”,再继续下一步。不要图省事把一堆清理命令写成一个大串并加上-y参数一次性执行,我在刚接触的时候因为apt autoremove -y吃过亏,虽然最终没造成严重后果,但过程足够惊悚。

清理本身是一种维护动作,它不是一次性把系统“弄干净”就结束,而是每隔一段时间重复做一轮。配合定时任务之后,手动清理的压力会越来越小。这篇文章写的每一步,都是我自己在桌面上反复验证过、在服务器上实际用过的,照着做,正常情况下不会出问题。如果哪一步的结果跟预期不一致,先停下来,用日志和命令输出核对一下,安全永远排在空间前面。希望这套流程能帮你把那台“满到报警”的 Ubuntu 救回来。

返回列表