服务器磁盘被谁吃掉了(2026 实操):从 df 追到 du,宝塔监控库一个文件占 4.4G

69% 的时候我才想起来看它

我的服务器是一台 2 核 1.9G 的 CentOS7,系统盘 40G。这天敲 df -h 的时候才注意到已经用掉 26G,剩 12G,占用 69%。

没报警,但心里不踏实。我自己清楚这台机器上最占地方的东西要么是备份,要么是监控数据,要么是某个被我忘了的日志,三种都不是网站本身。所以这次不猜,一层层往下追。

第一步:df 定范围,du 切开看

df -h 只是告诉你哪个分区满了,具体谁占的得靠 du。

du -xh --max-depth=1 / 2>/dev/null | sort -rh | head -10

-x 别省,它让 du 不跨文件系统,不然挂载点、/proc 这些会把命令拖到没边,输出还一堆噪音。--max-depth=1 是只看根目录下一层,sort -rh 按大小倒着排。

输出是这样:

26G	/
19G	/www
4.2G	/usr
1.3G	/root
1.2G	/var
701M	/opt
103M	/boot
57M	/etc

大头在 /www。继续切:

du -xh --max-depth=1 /www | sort -rh | head
find / -xdev -type f -size +200M -printf "%s\t%p\n" 2>/dev/null | sort -rn | head

第二条是抓单个大文件,比一层层 du 快得多,200M 这个阈值按你的盘调,盘小就用 50M。加上 2>/dev/null,不然 /proc 和权限不足的目录会刷一屏报错。

结果很集中:/www/server 16G,其中 /www/server/monitor 6.8G,/www/server/panel 3.1G,/www/server/mysql 2.2G。单个文件排第一的是哪个?

/www/server/monitor/data/dbs/littlesheep.cc/uri_list.db,4.66GB。

第二步:看看这个文件到底是什么

ls -lh 显示 4.4G,du 显示 4.3G,两个数不一样是因为一个按 1000 算一个按 1024 算,别为这个数纠结。

它是 SQLite 库,用面板自带的 sqlite3 看一眼结构:

cd /www/server/monitor/data/dbs/littlesheep.cc
sqlite3 uri_list.db ".tables"
sqlite3 uri_list.db "select sql from sqlite_master where name='uri_list'"

只有一张表,三个字段:

CREATE TABLE `uri_list` (
    `uri_id` INTEGER PRIMARY KEY AUTOINCREMENT,
    `uri` TEXT DEFAULT "" NOT NULL, time INTEGER DEFAULT 0);
CREATE UNIQUE INDEX `idx_uri` ON `uri_list` (`uri`);

一条记录就是一个被访问过的 URL,uri 上还有个唯一索引。查一下自增 ID 排到哪了:

sqlite3 uri_list.db "select uri_id, substr(uri,1,60), datetime(time,'unixepoch','+8 hours') from uri_list order by uri_id desc limit 3"
1803174|/wp-content/plugins/developer-developer-|2026-10-11 12:28:29
1803173|/wp-content/plugins/jejejeremy-developer|2026-10-11 12:28:27

18 万个 URL 量级已经在往两百万走,最新的一条是刚刚写进来的。看 URL 的模样就明白了:全是扫描器在猜插件路径。这类垃圾 URL 又长又随机,一天几千上万条,宝塔的策略是每个新 URL 存一行、永不重复,攒上一年就是几个 G。

这里有个细节能说明问题:用 PRAGMA freelist_count 查空闲页,返回 0。意思是这 4.4G 全是真实数据占着的,没有碎片可以捡,光 VACUUM 一次不会瘦,必须先把老数据删掉。

第三步:清理,三种力度按需要选

1. 面板里清。 软件商店找到「网站监控报表」,插件设置里有数据保存时间;面板左侧「监控」页右上角也有清空记录。不同宝塔版本的菜单位置会变,按你自己的面板为准,能点就别敲命令。

2. 删旧的按天文件。 这个目录下还有 access-20260729.db、error-20260729.db 这种按天切的小库,一个不到 100K:

ls -lh /www/server/monitor/data/dbs/*/access-2026*.db | head

三十天前的直接删,监控报表里看不到那么久以前的明细,不影响总量统计。

3. 命令行删老行,把大头拿回来。 顺序别乱,尤其是先停服务:

systemctl stop monitor
cd /www/server/monitor/data/dbs/littlesheep.cc
cp -a uri_list.db /www/backup/uri_list.db-$(date +%F)
sqlite3 uri_list.db "select count(*) from uri_list where time > 0 and time < strftime('%s','now') - 2592000"

最后这条是数一下 30 天前的行有多少。4G 的库做 count 要扫全表,慢是正常的,如果磁盘已经很紧张就别做,直接进下一步。数完删除加回收:

sqlite3 uri_list.db <<'SQL'
DELETE FROM uri_list WHERE time > 0 AND time < strftime('%s','now') - 2592000;
VACUUM;
SQL
chown bt-monitor:bt-monitor uri_list.db*
systemctl start monitor

几个必须注意的点。删了行空间不会自己还回来,SQLite 只是把页标成空闲,得靠 VACUUM 重写整个库才真的释放,而 VACUUM 需要一个跟原库差不多大的临时空间,动 4.4G 的库之前先用 df -h 确认还有 5G 以上余量。库文件属主是 bt-monitor,你是 root 跑 sqlite3,收尾必须 chown 回去,不然监控写不进数据。time = 0 的那批是最早入库、还没时间戳字段的老记录,删不删看你自己,我留着了,量不大。

还有个小坑:CentOS7 自带的 sqlite3 是 3.7.17,2013 年的版本,-readonly 这种参数它不认,网上有些命令直接抄会报 unknown option,以你的 sqlite3 --version 为准。

顺手把这几处也过一遍

systemd 日志。 journalctl --disk-usage 显示 616M。临时清:journalctl --vacuum-size=200M。想长期压住就在 /etc/systemd/journald.conf 的 [Journal] 段加 SystemMaxUse=200M,然后 systemctl restart systemd-journald。

面板自己的库。 /www/server/panel/data/system.db 1.7G,这是面板设置和统计的数据,论坛里有帖子教人直接 rm 它再重启面板,我建议别这么干,删了面板配置跟着丢,1.7G 换不来多少空间。

网站日志。 我的 /www/wwwlogs 一共 13M,因为 logrotate 已经在按天切:

/www/wwwlogs/littlesheep.cc.log
/www/wwwlogs/littlesheep.cc.error.log {
    daily
    rotate 7
    compress
    delaycompress
    missingok
    notifempty
    copytruncate
    dateext
}

copytruncate 是关键,nginx 不支持自己重开日志文件,只能把内容复制走再清空原文件。改完配置先用 logrotate -d /etc/logrotate.d/littlesheep 干跑一遍,-d 只打印它会做什么,不会真动文件。

已删除但没释放的文件。 如果 df 和 du 差了好几个 G,八成是某个进程还攥着已经 rm 掉的日志句柄:

lsof -nP 2>/dev/null | grep deleted

我这次就查出一条:history 进程还捏着 49M 的 /var/log/secure-20260809。这种只能重启对应进程才放得出来。

怎么确认真的省出来了

动过手之后重新跑一遍 df -h 和 du -sh /www/server/monitor,两个数都得降。再打开面板的监控报表,看访问量、IP 统计这些总量页正不正常,明细里 30 天前的没了是预期内的。

真出问题就回滚:停服务,把备份的 cp -a /www/backup/uri_list.db-2026-10-11 uri_list.db 盖回去,chown 之后起服务。所以备份这一步别偷懒,cp -a 的 -a 保留属主权限,能省掉后面一半麻烦。

磁盘清理这事没什么技术含量,难的是别慌。df 定范围、du 切层次、find 抓文件,三步下来答案自己就浮出来了,比乱删日志稳妥得多。备份和恢复我在这篇 WordPress 全站自动备份与恢复 里写过完整方案,日志和缓存相关的坑可以看 WordPress 502 和白屏排障 那篇。下次再遇到面板报磁盘满,至少知道先从哪个数开始看。

© 版权声明
THE END
喜欢就支持一下吧
点赞13 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容