运行 Web 服务器、数据库和应用程序的 VPS 会持续积累日志文件。当磁盘填满时,您的网站会崩溃,数据库停止写入新数据,整个服务器可能无法响应请求。Logrotate 是 Linux 系统上的标准日志管理工具,可以按计划自动轮换、压缩和删除旧日志,是每台 VPS 服务器的必配基础工具。
许多系统管理员忽视了日志管理,直到磁盘空间耗尽才追悔莫及。Nginx、MySQL、应用程序错误日志在高流量服务器上每天可产生数 GB 数据。没有轮换策略,这些文件会无限增长,最终在最不合时宜的时刻让整台服务器停摆。本指南帮助您为所有主要服务配置 Logrotate,并介绍如何管理 systemd 日志,确保磁盘空间始终处于可控状态。
Logrotate 是什么?为什么需要它?
Logrotate 是一个自动化的日志管理工具,可以定期重命名旧日志文件、创建新日志文件、对旧日志进行 gzip 或 bzip2 压缩、最后删除超过保留期限的文件。这一切都通过 cron 任务完全自动化进行,无需手动干预。
想象一个场景:您的 Nginx 服务器每天产生 1GB 的访问日志和 500MB 的错误日志。不经过处理,一个月就会产生 45GB 的日志数据。如果您的 VPS 只有 100GB 存储,不到 2 个月就会填满。Logrotate 会自动:
- 将当前日志重命名为带日期的存档文件(如 access.log.1)
- 创建新的日志文件供应用继续写入
- 向应用程序发送信号,告诉它重新打开日志文件
- 对旧日志进行 gzip 压缩(通常能压缩 80% 的大小)
- 删除超过指定天数的日志文件
通过 Logrotate,同样的 45GB 月度日志数据可以被压缩到只需 8-10GB 存储空间,并且可以根据您的需要自动删除 30 天前的日志。
Logrotate 的关键配置文件和位置
Logrotate 的配置存储在几个关键位置:
/etc/logrotate.conf # 全局默认配置
/etc/logrotate.d/ # 按服务分类的配置目录
/var/lib/logrotate/status # 轮换历史和状态文件
主配置文件 /etc/logrotate.conf 定义了所有日志的全局默认值,而 /etc/logrotate.d/ 目录中的文件允许为特定服务(如 Nginx、MySQL)定义自定义规则。当您创建新的轮换规则时,通常会在 /etc/logrotate.d/ 中创建一个新文件。
您可以查看当前配置:
cat /etc/logrotate.conf
# 查看 Nginx 的特定配置
cat /etc/logrotate.d/nginx
Logrotate 常见选项详解
了解各个配置选项的含义是正确设置 Logrotate 的关键:
daily/weekly/monthly— 轮换频率(每天/周/月)rotate N— 保留多少个旧日志备份(通常 7-30)compress— 立即使用 gzip 压缩旧日志delaycompress— 延迟压缩到下一次轮换时(配合 compress 使用)missingok— 如果日志文件不存在,不报错继续notifempty— 如果日志文件为空,跳过轮换create 640 user group— 轮换后创建新日志文件并设置权限copytruncate— 复制日志内容后清空原文件(不需要应用重新打开文件)size 100M— 当日志文件达到指定大小时轮换,不考虑日期postrotate/endscript— 轮换后执行的命令块(如发送 HUP 信号给应用)sharedscripts— postrotate 块中的脚本只运行一次,即使多个日志文件匹配
Nginx 日志轮换配置
Nginx 通常已经在 Ubuntu/Debian 系统中预配置了 Logrotate。查看现有配置:
cat /etc/logrotate.d/nginx
标准的 Nginx 配置通常看起来像这样:
/var/log/nginx/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 640 www-data adm
sharedscripts
postrotate
if [ -f /var/run/nginx.pid ]; then
kill -USR1 `cat /var/run/nginx.pid`
fi
endscript
}
这个配置的含义:
- daily — 每天检查一次是否需要轮换
- rotate 14 — 保留 14 个日志文件(约 2 周)
- compress + delaycompress — 压缩旧日志,但不压缩最新的备份(因为 Nginx 可能仍然持有文件句柄)
- create 640 www-data adm — 创建新日志文件,权限为 640,所有者为 www-data 用户
- postrotate USR1 — 向 Nginx 进程发送 USR1 信号,让它重新打开日志文件,无需完全重启
这种配置对高流量网站至关重要。USR1 信号允许在不中断服务的情况下进行日志切换,避免请求丢失。
MySQL 和 MariaDB 日志轮换
MySQL 的慢查询日志和错误日志往往会占用大量磁盘空间。为 MySQL 创建自定义轮换规则:
sudo nano /etc/logrotate.d/mysql
添加以下内容:
/var/log/mysql/mysql-slow.log
/var/log/mysql/error.log {
daily
rotate 7
missingok
compress
delaycompress
notifempty
create 640 mysql adm
postrotate
mysqladmin -u root -p'YOUR_ROOT_PASSWORD' flush-logs 2>/dev/null
endscript
}
配置说明:
- rotate 7 — 只保留 7 天的日志(MySQL 日志通常增长快)
- postrotate mysqladmin flush-logs — 轮换后通知 MySQL 关闭旧日志并打开新日志
- 使用
mysqladmin flush-logs比直接发送信号更安全,它确保缓冲的日志数据被写入
确保将 YOUR_ROOT_PASSWORD 替换为实际的 MySQL root 密码。为了更安全,您也可以将凭据放在 ~/.my.cnf 文件中。
自定义应用程序日志轮换
对于您开发或运行的自定义应用程序,可能需要创建特定的轮换规则:
sudo nano /etc/logrotate.d/myapp
示例配置:
/var/www/myapp/logs/*.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
copytruncate
su www-data www-data
}
这个配置:
- rotate 30 — 保留 30 个日志备份(一个月的日志)
- copytruncate — 复制日志后清空,适合不支持信号重新打开的应用
- su www-data www-data — 以 www-data 用户身份执行轮换(重要,以便正确设置文件所有权)
copytruncate 选项适合那些不支持优雅日志重新加载的应用程序。它会复制日志文件的内容到存档,然后清空原文件,应用程序继续向空文件写入。这种方式在复制过程中可能丢失少量日志,但对大多数应用来说可以接受。
基于文件大小的日志轮换
有时候按日期轮换不适合所有场景。对于产生日志非常快的应用,可以改用基于大小的轮换:
/var/log/myapp/access.log {
size 100M
rotate 5
compress
missingok
copytruncate
}
这个配置在以下情况下很有用:
- 高流量应用可能在一天内生成超过 100MB 的日志
- 无法预测日志大小增长的应用
- 需要更频繁轮换以节省磁盘空间的情况
当日志文件达到 100MB 时,无论当前日期如何,都会立即进行轮换。这种方式允许更灵活的日志管理。
测试和调试 Logrotate 配置
在部署新配置之前,始终要先进行测试:
# 干运行 - 显示将要执行的操作,不实际修改文件
sudo logrotate -d /etc/logrotate.conf
# 强制执行轮换(用于测试)
sudo logrotate -f /etc/logrotate.d/nginx
# 详细输出模式
sudo logrotate -v /etc/logrotate.conf
# 查看轮换历史记录
sudo cat /var/lib/logrotate/status
特别是 -d(干运行)选项非常重要。它会显示 Logrotate 如何解释您的配置规则以及会执行哪些操作,但不会实际修改任何文件。这样您可以在应用到生产系统之前验证配置的正确性。
/var/lib/logrotate/status 文件记录了每个日志文件上次轮换的时间戳。如果您想强制立即进行轮换(即使不满足时间条件),可以编辑此文件中的时间戳或使用 -f 标志。
最佳实践提示:每次创建或修改 Logrotate 配置时,始终先运行 sudo logrotate -d /etc/logrotate.d/yourconfig 进行验证。这可以在出现问题前发现 99% 的配置错误。
管理 systemd 日志和 Journal 日志
现代 Linux 系统使用 systemd 的 Journal 日志系统,它可以占用大量磁盘空间。特别是在运行许多服务或有大量日志输出的系统上,Journal 日志可以快速填满磁盘。
检查 Journal 日志占用的磁盘空间:
journalctl --disk-usage
清理 Journal 日志的方法:
# 删除 30 天以前的日志
sudo journalctl --vacuum-time=30d
# 限制日志总大小为 500MB
sudo journalctl --vacuum-size=500M
# 删除所有日志(谨慎使用)
sudo journalctl --flush --vacuum-size=1K
为了设置永久的日志保留策略,编辑 Journal 配置文件:
sudo nano /etc/systemd/journald.conf
添加或修改以下参数:
SystemMaxUse=500M
MaxRetentionSec=30day
MaxFileSec=1week
然后重启 Journal 服务:
sudo systemctl restart systemd-journald
这些参数的含义:
- SystemMaxUse — Journal 日志最大占用磁盘空间
- MaxRetentionSec — 保留日志的最长时间
- MaxFileSec — 单个日志文件的最长保存时间
诊断磁盘空间问题
当磁盘接近满容时,您需要快速诊断是哪些文件或目录占用了大量空间:
# 查看磁盘使用总情况
df -h
# 查看 /var/log 中各目录的大小(按降序排列)
du -sh /var/log/* | sort -rh | head -20
# 查看 /var/log 中所有超过 100MB 的文件
find /var/log -type f -size +100M -exec ls -lh {} \;
# 查看整个文件系统中哪些目录占用最多空间
du -sh /* | sort -rh | head -10
这些命令可以帮助您快速定位问题。例如,如果您发现 /var/log/mysql 占用 80GB,那么立即配置 MySQL 的日志轮换就很重要。
Logrotate 常见问题和解决方案
日志文件仍在增长,轮换未执行
可能的原因和解决方案:
- Logrotate cron 任务未启用 — 检查
/etc/cron.daily/logrotate是否存在且可执行 - 日志文件路径不匹配 — 确认实际文件位置与配置中的路径完全相同
- notifempty 导致未轮换 — 如果日志文件为空,notifempty 选项会跳过轮换
- 时间戳问题 — 检查
/var/lib/logrotate/status中的时间戳是否正确
轮换后应用程序停止写入日志
这通常是因为应用程序没有重新打开日志文件:
- 在 postrotate 块中添加适当的重新加载命令
- 对于 Nginx:
kill -HUP $(cat /var/run/nginx.pid)或nginx -s reload - 对于 Apache:
systemctl reload apache2 - 对于自定义应用:确认应用支持 SIGHUP 信号或实现日志重新打开机制
轮换脚本权限错误
如果出现权限拒绝错误:
- 确保
su username group选项中的用户和组正确 - 验证日志文件的实际所有者:
ls -l /var/log/yourlogfile - 确保 Logrotate 的 create 选项中的权限对应用程序的可写性足够
完整配置示例:生产环境最佳实践
这是一个针对典型 LAMP/LEMP 堆栈的完整配置示例:
# /etc/logrotate.d/webserver-complete
/var/log/nginx/*.log
/var/log/apache2/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
create 640 www-data adm
sharedscripts
postrotate
systemctl reload nginx > /dev/null 2>&1 || true
systemctl reload apache2 > /dev/null 2>&1 || true
endscript
}
/var/log/mysql/*.log {
daily
missingok
rotate 14
compress
delaycompress
notifempty
create 640 mysql adm
postrotate
mysqladmin flush-logs > /dev/null 2>&1 || true
endscript
}
/var/www/*/logs/*.log {
daily
missingok
rotate 30
compress
delaycompress
notifempty
copytruncate
su www-data www-data
}
这个配置为您的整个 VPS 提供了全面的日志管理。根据您的具体情况调整参数:
- 高流量网站:增加 rotate 值到 60-90 天
- 低流量网站:可以减少到 7-14 天
- 大量应用日志:考虑使用基于大小而非日期的轮换
- 关键应用:保留更多历史以便故障排查
需要具有完全控制的 Linux VPS?
AsiaGB VPS 运行 Ubuntu/Debian,具有 root 访问权限 — 完全按照您的需要管理日志、cron 和服务。我们的 VPS 配有 99% 的正常运行时间 SLA 和 SSD 存储,起价仅 500 泰铢/月。
查看VPS套餐