日志是排查问题的重要依据,但不加管理的日志文件会悄悄吃满磁盘,轻则 Web 服务写入报错,重则系统无法正常运行。在搬瓦工 VPS 这类磁盘有限的环境中,建立良好的日志轮转与磁盘清理习惯尤为重要。本文介绍 logrotate 的配置、systemd journal 日志清理,以及找出大文件和定期清理的实用命令。
本文要点
- logrotate 自动按周期轮转并压缩日志,防止单文件无限增长
- systemd journal 日志占用可能几 GB,定期清理很有必要
du+find快速找出磁盘空间杀手- 设置合理的保留周期,平衡排查需求与空间占用
logrotate 基础
logrotate 是 Linux 标准的日志轮转工具,绝大多数发行版默认已安装。它定期(每日/每周)对日志文件进行轮转:重命名旧日志、压缩存档、删除超出保留期的旧文件,并可在轮转后重启相关服务让其写入新日志。
# 查看 logrotate 是否已安装
which logrotate
# 查看全局配置
cat /etc/logrotate.conf
# 各应用的专属配置目录
ls /etc/logrotate.d/logrotate 配置详解
以 Nginx 日志为例,展示一个完整的轮转配置:
/var/log/nginx/*.log {
daily # 每天轮转
missingok # 日志文件不存在也不报错
rotate 14 # 保留最近 14 份(超出的自动删除)
compress # 旧日志用 gzip 压缩
delaycompress # 保留最近一份不压缩(方便当天查看)
notifempty # 文件为空时不轮转
create 0640 www-data adm # 轮转后新建日志文件并设权限
sharedscripts
postrotate
# 让 nginx 重新打开日志文件
nginx -s reopen 2>/dev/null || true
endscript
}| 指令 | 含义 |
|---|---|
| daily / weekly / monthly | 轮转周期 |
| rotate N | 保留最近 N 份,超出自动删除 |
| compress / delaycompress | gzip 压缩旧日志,最近一份延迟压缩 |
| missingok | 日志不存在时跳过,不报错 |
| notifempty | 日志为空时不轮转 |
| postrotate | 轮转后执行的命令(通常是重载服务) |
手动测试 logrotate
# 模拟运行(不实际轮转),查看会处理哪些日志
logrotate --debug /etc/logrotate.conf
# 强制立即轮转(不管是否满足周期条件)
logrotate --force /etc/logrotate.d/nginx
# 查看 logrotate 上次运行状态
cat /var/lib/logrotate/statuspostrotate 必须通知服务重新打开日志
postrotate 中通知服务(如 nginx -s reopen、systemctl reload php-fpm)重新打开新日志文件,否则轮转无效。清理 systemd journal 日志
systemd-journald 会持久化系统日志,长期运行后可能占用数 GB。定期清理可释放大量空间:
# 查看当前 journal 占用
journalctl --disk-usage
# 保留最近 7 天的日志(删除更早的)
journalctl --vacuum-time=7d
# 限制总占用不超过 500 MB
journalctl --vacuum-size=500M
# 设置永久限制:编辑 /etc/systemd/journald.conf
# [Journal]
# SystemMaxUse=500M
# MaxRetentionSec=7day
# 改完后重启 journald
systemctl restart systemd-journald查找磁盘空间占用大文件
# 查看各目录磁盘占用(从根目录开始,按大小排序)
du -sh /* 2>/dev/null | sort -rh | head -20
# 查找 /var 下最大的文件
du -sh /var/* | sort -rh | head -10
# 找出大于 100MB 的文件
find / -maxdepth 6 -type f -size +100M 2>/dev/null
# 查看 /var/log 下各日志大小
du -sh /var/log/* | sort -rh | head -20定期清理的最佳实践
- 用
df -h监控各分区使用率,磁盘超 80% 时应立即清理 - 定期删除 /tmp 下的临时文件:
find /tmp -mtime +7 -delete - 清理 apt/yum 缓存:
apt clean(Debian)或yum clean all(CentOS) - 检查 Docker 镜像和容器:
docker system prune -f(如使用 Docker) - 删除长期不用的备份文件和压缩包
设置磁盘告警
0 8 * * * df -h | awk 'NR>1 && int($5)>85{print}' | mail -s '磁盘告警' you@example.com这样磁盘快满时你能提前收到通知,避免服务受影响。
小结
- logrotate 配置
rotate保留份数 +compress压缩,是防止日志爆盘的标准方案 - postrotate 一定要通知服务重开日志,否则轮转无效
- journal 日志定期清理,建议限制在 500 MB 以内
du -sh /* | sort -rh是找磁盘空间占用的快捷入口- 磁盘超 80% 立即处理,超 90% 可能导致服务异常
常见问题
logrotate 已经配置了,为什么日志还是很大?
可能是服务没有响应 postrotate 的信号,仍在写旧文件。检查旧日志文件是否还在被写入:lsof | grep log | grep deleted,有输出说明存在被删除但仍在写的文件,需重启相关服务。
/var/log 下有很多 .gz 文件,可以直接删除吗?
可以,这些是 logrotate 压缩的旧日志归档。删除前确认其时间范围是否还在你的排查需求范围内;如果已超过保留期且无排查需求,可以安全删除。
磁盘满了但找不到大文件,怎么回事?
可能是有进程持有已删除文件的文件描述符(常见于日志轮转后未重启服务)。用 lsof | grep deleted | sort -k 7 -rn | head 查找被占用的"幽灵文件",重启相关服务即可释放空间。
journal 清理后磁盘空间没有释放?
journal 清理后需等文件系统同步,或用 sync 强制刷盘。也可检查 /run/log/journal(内存日志)是否也占用了大量空间,用 journalctl --flush 将其持久化再清理。