阿里云服务器磁盘空间还在涨?一次排查 WordPress 主机空间异常增长的完整记录

最近在检查自己的 WordPress 服务器时,发现磁盘空间还在不断增长。机器本身配置不大,40GB 硬盘,跑的是 Debian 11、Nginx、PHP 8.3、MySQL 8.0 和 WordPress,站点部署在新加坡区域的阿里云服务器上,主要面向中国大陆访问。

这类机器最怕的不是瞬间爆满,而是空间一点点上涨,却一时看不出是谁在吃盘。这次我就完整排查了一遍,最后确认问题不在备份目录,而是在 Redis 及其残留的快照文件上。过程中也顺手厘清了 MySQL、日志、上传目录这些常见嫌疑项。

这篇文章把整个过程整理下来。

一、发现问题:服务器空间持续增长

最开始的判断很简单:服务器空间在涨,但又不像是正常的文章、图片增长速度。因为 WordPress 站点虽然会上传图片和视频,但近期的增长幅度感觉不太对。

排查这类问题,第一步不能靠猜,先看整体磁盘占用。

df -h
df -ih
du -xhd1 / | sort -h

从顶层目录占用来看,当时机器大致是这样:

  • /home 占用最大
  • /usr 其次
  • /var 反而没有特别夸张

这一步很关键,因为它直接说明:问题大概率不在系统日志失控,也不是 /var 下面的常规服务暴涨,而更可能在站点目录、数据库目录或者某些手工安装的服务数据里。

二、先排除最常见嫌疑:备份目录

AMH 面板环境里,一个很常见的空间杀手就是本地备份。尤其是计划任务开启后,备份文件可能在 /home/backup 下面越积越多。

所以我先检查了备份目录。

du -sh /home/backup
ls -lh /home/backup

结果看下来,/home/backup 里虽然有备份文件,但并不是这次空间持续增长的主因。这个方向可以先排除。

这一步虽然没解决问题,但也很重要。很多时候排查卡住,不是因为不会查,而是因为没有及时排除错误方向。

三、继续往下钻:找全盘大文件

既然不是备份,那就直接找系统里最大的文件。

find / -xdev -type f -printf '%s %p\n' 2>/dev/null | sort -n | tail -50

这一查,信息就很明确了。大文件主要分成几类:

1. WordPress 上传目录里的大媒体文件

站点 wp-content/uploads 里有几个比较大的 .mov.mp4 和图片文件,比如:

  • 290MB 的 .mov
  • 191MB 的 .mp4
  • 133MB 的 .mov
  • 114MB 的 .mov

这说明站点本身确实会吃空间,特别是如果直接把视频传进 WordPress 媒体库,本地盘增长会很快。

但这些文件虽然大,却更像是正常业务占用,而不是“突然异常增长”的元凶。

2. MySQL 相关文件

我还看到了一些 MySQL 文件,比如:

  • undo_001
  • undo_002
  • ibdata1
  • ibtmp1

其中 undo_001 和 undo_002 都是 16MB 左右。

这两个文件一开始看着挺像“陌生大文件”,但实际上它们是 MySQL / InnoDB 的 undo tablespace 文件,主要用于事务回滚、MVCC 一致性读和崩溃恢复。它们属于数据库核心文件,不能乱删,而且体积也不大,根本不是主因。

另外我还发现机器里同时存在:

  • mysql-generic-5.7
  • mysql-generic-8.0

说明之前升级 MySQL 时,旧版本目录还留着。不过进一步查看后发现,5.7 目录只有一百多 MB,属于历史遗留,占空间但不是最近持续增长的核心原因。

3. Redis 相关文件

真正开始可疑的是 Redis 这一块。

我在大文件列表里看到了两个非常扎眼的文件:

  • /dump.rdb,48MB
  • /temp-1902.rdb,356MB

注意,是直接出现在根目录 / 下。

这就不太正常了。因为我的 WordPress 本身并没有使用 Redis 对象缓存,而根目录下居然躺着一个 356MB 的 Redis 快照文件,这明显值得深挖。

四、确认 Redis 真的在运行

虽然站点没用 Redis,但机器上 Redis 服务并没有停。

先查进程和监听端口:

ps -ef | grep redis
ss -lntp | grep 6379

结果确认:

  • Redis 服务确实在运行
  • 监听在 127.0.0.1:6379
  • 不是 systemd 管理的服务

进一步看路径,Redis 程序在:

/usr/local/redis-8.0/bin/redis-server
/usr/local/redis-8.0/bin/redis-cli

也就是说,这不是 Debian 默认 apt 装出来的标准路径,更像是通过面板或手工方式部署的 Redis。

这里还踩了一个小坑:因为系统里没有 redis-cli 的 PATH,所以直接敲 redis-cli 会提示找不到命令。实际上它是存在的,只是不在环境变量里,需要用完整路径调用。

五、一个小误判:不是 sudo 问题,而是环境本来就没有 sudo

在最开始跑排查命令时,我习惯性用了 sudo

sudo du -xhd1 / | sort -h

结果直接报错:

-bash: sudo: command not found

这个错误很容易让人下意识以为是权限问题,但实际上不是。我当时登录的就是 root,所以这台机器只是根本没装 sudo。这种情况在精简 VPS 或某些面板环境里很常见。

所以后面的命令直接去掉 sudo 就行。

六、确认不是 systemd 服务后,决定在 AMH 后台直接卸载 Redis

既然:

  • WordPress 没用 Redis
  • Redis 还在运行
  • Redis 快照文件还占着空间
  • 它又不是 systemd 管理的标准服务

那最稳妥的方式就不是手工删二进制,而是直接在 AMH 后台卸载 Redis

这么做的好处很明显:

  • 面板会顺手处理程序文件
  • 启动脚本更容易一起清掉
  • 不容易出现“二进制删了但面板里还残留服务记录”的情况

卸载完成后,我再次检查:

ps -ef | grep redis
ss -lntp | grep 6379

这时只剩下 grep redis 自己的进程,没有 Redis 服务本体,6379 端口也不再监听,说明 Redis 服务已经彻底停掉了。

七、清理 Redis 残留快照文件时,又踩了一个文件名坑

Redis 卸载后,根目录下的 RDB 文件还在。这时候它们就已经是纯残留文件了,可以直接删。

我原本执行的是:

rm -f /dump.rdb /temp-r1902.rdb

看起来像执行成功了,实际上只删掉了前一个文件。后面那个没删掉,因为我把文件名写错了。

真正存在的是:

/temp-1902.rdb

我多敲了一个 r,写成了 temp-r1902.rdb。而 rm -f 的特点是:即使目标文件不存在,也不会报错。所以表面上看像是执行成功,实际上文件还留着。

后来重新检查:

ls -lh / | grep rdb

才发现 /temp-1902.rdb 还在。最后用正确文件名删除:

rm -f /temp-1902.rdb

这一步清掉以后,Redis 这部分占用才算真的处理完。

八、这次实际清理掉了什么

这次和 Redis 直接相关、实际回收的空间大概是:

  • dump.rdb:48MB
  • temp-1902.rdb:356MB

加起来接近 400MB。

对一台 40GB 磁盘的主机来说,这不算毁灭性空间,但对长期运行的小 VPS 来说,已经是值得处理的一块了。更重要的是,这部分本来就是没必要存在的占用

九、journal 日志不是主因,收缩也没释放多少空间

我还顺手检查了 journal 日志占用:

journalctl --disk-usage

当时日志占用大概 256MB,看着不算特别小,所以又执行了一次:

journalctl --vacuum-size=100M

但结果显示释放了 0B。说明这部分虽然看起来占用不低,但并不是可清理归档日志大量堆积,当前并不是这次磁盘增长的主要原因。

这一步的意义更多在于排除,而不是解决。

十、这次排查后,我对服务器空间增长的判断

这次处理完以后,结论就比较清楚了:

已经确认并处理掉的

  • Redis 服务仍在运行,但站点并未实际使用
  • Redis 在根目录留下了快照文件
  • 其中 temp-1902.rdb 占了 356MB
  • Redis 已通过 AMH 后台卸载
  • RDB 残留文件已手动清理

已确认不是主因的

  • /home/backup 不是这次持续增长的核心来源
  • MySQL 的 undo_001undo_002 属于正常数据库文件,不是问题根源
  • journal 日志不是主要增长点
  • MySQL 5.7 旧目录虽然是遗留占用,但体积不大,也不是最近持续增长的主因

后续还要长期关注的

  • wp-content/uploads 的增长速度
  • 是否有大视频直接传到 WordPress 媒体库
  • 老旧媒体文件是否需要迁移到对象存储
  • MySQL 旧版本目录后续是否可以彻底清理

十一、这次排查里最值得记住的几个经验

1. 先看顶层目录,不要一上来就乱删

先用 df -hdu -xhd1 / 这类命令确认大方向,比盲猜有效得多。

2. 陌生文件不等于垃圾文件

像 MySQL 的 undo_001undo_002,看着不认识,但属于数据库核心文件,不能因为名字陌生就删。

3. rm -f 很安静,安静不代表删对了

这次 temp-1902.rdb 没删掉,就是典型例子。命令没报错,不代表目标文件真的被删了。

4. 面板环境下,优先用面板卸载组件

像 Redis 这种通过 AMH 管理的服务,直接在后台卸载,通常比手工删除更稳。

5. 小机器更要避免无意义常驻服务

本来就没用 Redis,却让它一直运行、一直可能生成快照文件,这对小配置 VPS 来说完全是额外负担。

十二、我最后的处理建议

如果你也遇到 WordPress 服务器空间持续增长,建议按这个顺序排查:

先看整体挂载点占用:

df -h
du -xhd1 / | sort -h

再找大文件:

find / -xdev -type f -printf '%s %p\n' 2>/dev/null | sort -n | tail -50

如果发现 Redis、MySQL、日志或备份相关目录,再分别深入看。

对于 WordPress 主机,最常见的几个增长源通常是:

  • 本地备份
  • 上传目录大媒体文件
  • Redis / MySQL 残留数据
  • 过大的日志
  • 缓存插件目录

这次我的情况,最终就是 Redis。


这次排查不算复杂,但过程很典型:先排除备份,再排除日志,再确认数据库文件不是主因,最后锁定 Redis 与残留快照文件。
很多时候服务器空间异常,并不是某个特别高级的问题,而是一个根本没在用的服务,悄悄在后台留下了不该留下的东西。

对于小配置机器来说,少一个无用服务,往往比多做一次优化更有价值。


Debian 10 + AMH:硬盘占用异常增长,定位到 MySQL Binlog 并彻底解决

最近发现服务器硬盘占用持续上升,而且增长偏快。环境是 Debian 10.5 + AMH 面板 + MySQL 8(mysql-generic-8.0),最终定位到 **MySQL 二进制日志(binlog)**在持续写入并占用空间。本文记录完整排查与解决流程。

现象

  • df -h 显示根分区占用在增长(虽未满,但趋势异常)
  • du 分析目录后发现 /home 占用较大
  • 进一步排查发现 MySQL 目录下存在不断变大的 binlog.* 或 mysql-bin.* 文件

一、定位是哪个目录在增长

先确认哪个挂载点在涨:

df -h
df -i

然后用 du 分层定位大目录(不跨文件系统):

du -x -h --max-depth=1 / | sort -h

这次结果显示 /home 是占用大头,于是继续下钻并找最近变大的大文件:

find /home/usrdata -xdev -type f -mtime -7 -size +50M -printf '%TY-%Tm-%Td %TH:%TM %s %p\n' 2>/dev/null | sort -nr | head -50

输出里直接命中 MySQL 的 binlog 文件(如 binlog.000001、binlog.000002 等)。

二、确认 MySQL 正在写 Binlog

在 phpMyAdmin 里通过 SQL 确认 binlog 状态:

SHOW VARIABLES LIKE 'log_bin';
SHOW VARIABLES LIKE 'log_bin_basename';
SHOW MASTER STATUS;
SHOW BINARY LOGS;

关键点:

  • log_bin = ON 说明 binlog 开着
  • log_bin_basename 能确认 binlog 前缀(例如 /home/usrdata/mysql-generic-8.0/binlog)
  • SHOW MASTER STATUS 的 File 表示当前正在写的 binlog 文件

三、踩坑记录:不要用 rm 直接删正在被 MySQL 管理的 binlog

这次过程中曾经用 rm 直接删除 binlog.000001~000005,导致后续在 phpMyAdmin 执行 purge 报错:

  • File ‘./binlog.000005’ not found (OS errno 2)

原因是:MySQL 仍保存着 binlog 的索引与状态,但实际文件已被手动删除,导致状态与磁盘不一致。

正确做法应该优先使用:

PURGE BINARY LOGS ...

或用更彻底的方式重建状态(见下文)。

四、最终解决方案:永久关闭 Binlog + 重置状态 + 清理残留文件

对于单机 WordPress(不做主从复制、也不依赖 binlog 做点时间恢复),最省心的方案是永久关闭 binlog

1)在 AMH 配置中强制关闭 binlog

进入 AMH → MySQL → 编辑配置,在 [mysqld] 段加入:

disable_log_bin

保存后重启 MySQL。

2)验证已关闭

phpMyAdmin 执行:

SHOW VARIABLES LIKE 'log_bin';

确认返回 OFF。

3)重建/清空 binlog 状态(修复“删文件导致索引错乱”)

在 phpMyAdmin 执行:

RESET MASTER;

此时 binlog 的索引、状态会被重置,避免后续再出现“引用不存在文件”的报错。

4)删除残留的大 binlog 文件(此时可以 rm)

因为 log_bin=OFF 且已 RESET MASTER,MySQL 不再写也不再依赖这些文件,可以安全删除历史残留(例如 mysql-bin.000001 很大):

cd /home/usrdata/mysql-generic-8.0/
ls -lh | egrep "mysql-bin|binlog"
rm -f mysql-bin.000001 mysql-bin.000002
rm -f binlog.* 2>/dev/null
df -h

五、结果

  • MySQL binlog 不再生成,硬盘占用增长停止
  • 清理残留文件后释放了数百 MB 空间
  • MySQL 状态恢复一致,不再出现 “binlog not found” 类报错

补充建议

  • 如果你确实需要 binlog(主从复制/点时间恢复),不要关闭;应设置自动过期,例如:
SET PERSIST binlog_expire_logs_seconds=259200;
  • (保留 3 天,按需调整)

用 curl 和浏览器开发者工具检查网站是否启用了压缩(gzip/br)

前阵子我给自己的 WordPress 站点做了一轮优化,最先想确认的一件事就是:网页传输有没有启用压缩。不然同样的页面内容,带宽白白浪费,访问体验也不稳定。

我用的站点是:https://blog.sinovale.com,服务器是 Nginx。下面把我当时用到的检查方法整理成一篇可直接照抄的教程。


先搞清楚:我说的“压缩”是哪种?

很多人说“压缩”其实混在一起讲了两件事:

  • 传输压缩(HTTP 压缩):gzip / brotli(br)
    这是我这篇文章要检查的重点,能直接减少传输体积。
  • 资源压缩:比如 JS/CSS 的 minify、图片 WebP/AVIF
    这属于“内容本身更小”,和 gzip/br 不是一回事。

方法一:用浏览器开发者工具看响应头(最直观)

在电脑浏览器打开网页后:

  1. F12 打开开发者工具
  2. Network(网络)
  3. 刷新页面(Ctrl+R)
  4. 点开任意一个请求(建议先看首页 Document,再看 JS/CSS)
  5. Response Headers 里找:
  • content-encoding: gzip → 说明启用了 gzip 压缩
  • content-encoding: br → 说明启用了 brotli 压缩(通常压缩率更高)
  • 如果没有 content-encoding → 这条请求基本就是未压缩返回

另外,很多时候你还会看到 Size / Transferred

  • Transferred 明显小于 Size,通常也意味着压缩或缓存起作用(但最终还是以 content-encoding 为准)。

方法二:用 curl 一条命令确认(最准确、最省事)

我更喜欢用命令行,因为结论更硬。

1)检查首页 HTML 是否压缩

curl -I -H 'Accept-Encoding: gzip,br' https://blog.sinovale.com/

我这边的返回里有关键一行:

  • content-encoding: gzip

这就说明:首页 HTML 已经开启 gzip 传输压缩

同时还能看到:

  • server: nginx(确认是 Nginx 返回)
  • vary: Accept-Encoding, Cookie(告诉缓存层:不同压缩能力和 Cookie 会影响响应版本)

小提示:请求头里带上 Accept-Encoding: gzip,br 的意义是“我客户端支持 gzip 和 br”,服务器会从中选择它支持的方式返回。


再测两条:CSS 和 JS 有没有一起压缩(很多人漏在这里)

很多站只压了 HTML,结果 JS/CSS 没压,那体验还是差一截。所以我又测了两个典型静态文件:

2)测试 WordPress 自带的 CSS

curl -I -H 'Accept-Encoding: gzip,br' "https://blog.sinovale.com/wp-includes/css/dist/block-library/style.min.css"

返回包含:

  • content-encoding: gzip

说明 CSS 也在压缩。

3)测试 WordPress 自带的 jQuery

curl -I -H 'Accept-Encoding: gzip,br' "https://blog.sinovale.com/wp-includes/js/jquery/jquery.min.js"

返回同样包含:

  • content-encoding: gzip

说明 JS 也在压缩。

到这里基本可以下结论:我站点的 HTML / CSS / JS 都启用了 gzip 传输压缩。


为什么我没看到 br(brotli)?

即便我请求里写了 Accept-Encoding: gzip,br,服务器最后还是返回 content-encoding: gzip,一般意味着:

  • 服务器没有启用 brotli(Nginx 没装 brotli 模块或没开配置),或者
  • brotli 只对部分类型生效(但我这里 HTML/CSS/JS 都没返回 br,通常就是没启用)

我个人的选择是:gzip 够用就先不折腾。对小机器来说,brotli 的压缩率可能更好,但也可能带来更多 CPU 开销。除非你确定访客量大、带宽紧、并且愿意花时间把 brotli 模块装完整,否则 gzip 已经能解决 80% 的问题。


我额外建议再“体检”三类常见漏网之鱼

如果你也想检查得更彻底,可以再测这三类:

1)REST API(JSON)

curl -I -H 'Accept-Encoding: gzip,br' https://你的域名/wp-json/

看有没有 content-encoding: gzip

2)站点地图(XML)

curl -I -H 'Accept-Encoding: gzip,br' https://你的域名/sitemap.xml

看有没有 content-encoding: gzip

3)SVG(有些主题/图标会用)

curl -I -H 'Accept-Encoding: gzip,br' https://你的域名/xxx.svg

看有没有 content-encoding: gzip


总结

我的做法很简单:

  • 浏览器看 content-encoding(直观)
  • curl -I 看响应头(结论硬)
  • 再用 CSS/JS 验证一遍,避免“只压了 HTML”这种半套配置

到最后我确认:blog.sinovale.com 现在 gzip 压缩已启用,HTML/CSS/JS 都在压缩传输。