Linux logrotate命令详解
logrotate 是Linux系统中用于管理系统日志文件的工具,它可以自动轮转、压缩、删除和邮寄日志文件,防止日志文件无限增长占用磁盘空间,同时保持日志文件的完整性和可管理性。
1. 安装与基本配置
1.1 安装logrotate
大多数Linux发行版已经预装了logrotate。如果需要安装:
# Ubuntu/Debian
sudo apt-get update
sudo apt-get install logrotate
# CentOS/RHEL
sudo yum install logrotate
# 检查版本
logrotate --version
1.2 配置文件位置
| 文件/目录 |
用途 |
/etc/logrotate.conf |
主配置文件 |
/etc/logrotate.d/ |
应用程序特定的配置文件目录 |
/var/lib/logrotate/status |
记录logrotate执行状态的文件 |
2. 命令语法
logrotate [选项] 配置文件
3. 常用选项
| 选项 |
说明 |
-d 或 --debug |
调试模式,显示执行过程但不实际执行 |
-f 或 --force |
强制轮转,即使不符合条件 |
-v 或 --verbose |
详细模式,显示详细信息 |
-s 或 --state |
指定状态文件位置 |
-l 或 --log |
指定日志文件位置 |
--version |
显示版本信息 |
4. 配置文件语法详解
4.1 配置文件结构
# 全局配置选项(对所有日志生效)
全局选项
# 特定日志文件配置
/var/log/syslog {
配置选项
}
# 多个日志文件
/var/log/apache/*.log {
配置选项
}
4.2 常用配置选项
| 选项 |
说明 |
示例 |
daily/weekly/monthly |
轮转周期 |
daily |
rotate 数字 |
保留的旧日志文件数量 |
rotate 7 |
compress |
压缩旧日志 |
compress |
delaycompress |
延迟压缩 |
delaycompress |
missingok |
日志文件不存在时不报错 |
missingok |
notifempty |
日志文件为空时不轮转 |
notifempty |
create 模式 用户 组 |
创建新日志文件的权限 |
create 644 root root |
postrotate/endscript |
轮转后执行的脚本 |
postrotate systemctl reload nginx endscript |
size 大小 |
按大小轮转 |
size 100M |
dateext |
使用日期作为扩展名 |
dateext |
dateformat 格式 |
自定义日期格式 |
dateformat -%Y%m%d |
sharedscripts |
多个日志共享脚本 |
sharedscripts |
maxage 天数 |
保留日志的最大天数 |
maxage 30 |
mail address |
发送旧日志到指定邮箱 |
mail admin@example.com |
5. 基本配置示例
5.1 简单日志轮转配置
# /etc/logrotate.d/myapp
/var/log/myapp.log {
daily
rotate 7
compress
missingok
notifempty
create 644 myapp myapp
}
5.2 多文件轮转配置
# /etc/logrotate.d/apache
/var/log/apache2/*.log {
weekly
rotate 4
compress
delaycompress
missingok
notifempty
create 640 root adm
sharedscripts
postrotate
/etc/init.d/apache2 reload > /dev/null
endscript
}
5.3 按大小轮转配置
# /etc/logrotate.d/nginx
/var/log/nginx/*.log {
size 100M
rotate 10
compress
delaycompress
missingok
notifempty
create 644 www-data adm
sharedscripts
postrotate
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
endscript
}
6. 高级配置示例
6.1 自定义日期格式
/var/log/application.log {
daily
rotate 30
compress
dateext
dateformat -%Y%m%d-%s
missingok
notifempty
create 644 appuser appgroup
}
6.2 条件轮转和邮件通知
/var/log/secure.log {
weekly
rotate 8
compress
missingok
# 只在日志大于10M时才轮转
minsize 10M
# 发送旧日志到管理员邮箱
mail admin@example.com
mailfirst # 发送第一个删除的日志
maillast # 发送最后一个删除的日志
postrotate
/usr/bin/killall -HUP syslogd
endscript
}
6.3 复杂的脚本执行
/var/log/mysql/*.log {
daily
rotate 7
compress
delaycompress
missingok
create 640 mysql adm
prerotate
# 轮转前执行的脚本
if [ -d /etc/logrotate.d/httpd-prerotate ]; then
run-parts /etc/logrotate.d/httpd-prerotate
fi
endscript
postrotate
# 轮转后执行的脚本
if [ -e /var/run/mysqld/mysqld.pid ]; then
mysqladmin flush-logs
fi
endscript
}
7. 实际应用场景
场景1:Web服务器日志轮转
# /etc/logrotate.d/nginx-complete
/var/log/nginx/access.log
/var/log/nginx/error.log {
daily
rotate 30
compress
delaycompress
dateext
missingok
notifempty
create 640 www-data adm
sharedscripts
prerotate
if [ -d /etc/logrotate.d/nginx-prerotate ]; then
run-parts /etc/logrotate.d/nginx-prerotate
fi
endscript
postrotate
# 重新打开日志文件
[ ! -f /var/run/nginx.pid ] || kill -USR1 `cat /var/run/nginx.pid`
# 发送通知
echo "Nginx日志已轮转 $(date)" | mail -s "Nginx日志轮转通知" admin@example.com
endscript
}
场景2:数据库日志轮转
# /etc/logrotate.d/mysql-server
/var/log/mysql/mysql.log
/var/log/mysql/mysql-slow.log
/var/log/mysql/error.log {
daily
rotate 7
compress
delaycompress
missingok
notifempty
create 640 mysql adm
postrotate
# 如果MySQL正在运行,刷新日志
if test -x /usr/bin/mysqladmin && \
/usr/bin/mysqladmin ping &>/dev/null
then
/usr/bin/mysqladmin flush-logs
fi
endscript
}
场景3:自定义应用日志轮转
# /etc/logrotate.d/myapplication
/opt/myapp/logs/*.log {
size 50M
rotate 10
compress
delaycompress
missingok
notifempty
create 644 appuser appuser
# 最大保留90天
maxage 90
# 如果日志超过100M,立即轮转
maxsize 100M
postrotate
# 重启应用服务
systemctl restart myapp.service
# 记录轮转日志
echo "$(date): 应用日志已轮转" >> /var/log/logrotate.log
endscript
}
8. 手动执行和测试
8.1 手动执行logrotate
# 手动执行所有配置
sudo logrotate /etc/logrotate.conf
# 强制执行,即使未到轮转时间
sudo logrotate -f /etc/logrotate.conf
# 测试特定配置文件
sudo logrotate -d /etc/logrotate.d/nginx
# 强制执行并显示详细信息
sudo logrotate -vf /etc/logrotate.conf
8.2 调试和测试配置
# 调试模式(不实际执行)
sudo logrotate -d /etc/logrotate.conf
# 测试特定日志文件的配置
sudo logrotate -d /etc/logrotate.conf --debug | grep "myapp.log"
# 查看状态文件
sudo cat /var/lib/logrotate/status
# 重置状态文件(强制所有日志重新轮转)
sudo rm /var/lib/logrotate/status
sudo logrotate /etc/logrotate.conf
9. 定时任务配置
9.1 配置cron定时任务
# 查看logrotate的cron配置
sudo cat /etc/cron.daily/logrotate
# 文件内容通常如下:
#!/bin/sh
/usr/sbin/logrotate /etc/logrotate.conf
EXITVALUE=$?
if [ $EXITVALUE != 0 ]; then
/usr/bin/logger -t logrotate "ALERT exited abnormally with [$EXITVALUE]"
fi
exit 0
9.2 自定义执行时间
# 创建自定义cron任务
sudo nano /etc/cron.d/logrotate-custom
# 内容:每天凌晨2点执行logrotate
0 2 * * * root /usr/sbin/logrotate /etc/logrotate.conf > /var/log/logrotate_cron.log 2>&1
# 或者每小时执行一次(用于测试)
0 * * * * root /usr/sbin/logrotate /etc/logrotate.conf
10. 故障排除
问题1:日志轮转后服务无法写入新日志
# 检查文件权限和所有权
ls -la /var/log/nginx/
# 确保使用了正确的create选项
create 644 www-data www-data
# 检查postrotate脚本是否执行成功
sudo logrotate -vf /etc/logrotate.d/nginx 2>&1 | grep -A5 -B5 "postrotate"
# 手动重新加载服务
sudo systemctl reload nginx
问题2:日志未按预期轮转
# 检查状态文件
sudo cat /var/lib/logrotate/status | grep nginx
# 强制轮转并查看详细输出
sudo logrotate -vf /etc/logrotate.d/nginx
# 检查cron是否正常执行
sudo grep logrotate /var/log/syslog
# 检查日志文件大小
ls -lh /var/log/nginx/access.log
问题3:磁盘空间未释放
# 检查是否有进程仍持有旧日志文件的句柄
sudo lsof | grep deleted | grep log
# 如果有进程持有已删除文件的句柄,需要重启该进程
sudo systemctl restart nginx
# 检查压缩文件是否生成
ls -lh /var/log/nginx/*.gz
# 使用du命令查看实际磁盘使用
sudo du -sh /var/log/nginx/
11. 最佳实践
配置建议
- 合理设置保留周期:根据磁盘空间和合规要求设置rotate值
- 启用压缩:使用compress节省磁盘空间
- 使用delaycompress:避免压缩最近的日志,便于查看
- 配置postrotate脚本:确保服务能正确重新打开日志文件
- 使用sharedscripts:多个日志文件共享脚本,避免重复执行
- 监控logrotate执行:记录logrotate的执行日志
- 定期清理旧日志:使用maxage选项自动删除过旧日志
11.1 安全注意事项
# 1. 配置文件权限
sudo chmod 644 /etc/logrotate.d/your-config
sudo chown root:root /etc/logrotate.d/your-config
# 2. 避免在脚本中硬编码密码
# 3. 限制日志文件访问权限
create 640 username groupname
# 4. 定期审计logrotate配置
# 5. 监控异常轮转行为
12. 监控和调试脚本
1. logrotate执行监控脚本
#!/bin/bash
# /usr/local/bin/monitor-logrotate.sh
LOG_FILE="/var/log/logrotate_monitor.log"
CONFIG_FILE="/etc/logrotate.conf"
echo "=== Logrotate监控报告 $(date) ===" | tee -a $LOG_FILE
# 检查logrotate是否安装
if ! command -v logrotate &> /dev/null; then
echo "错误: logrotate未安装" | tee -a $LOG_FILE
exit 1
fi
# 测试配置文件语法
echo "测试配置文件语法..." | tee -a $LOG_FILE
if sudo logrotate -d $CONFIG_FILE 2>&1 | grep -q "error"; then
echo "发现配置错误:" | tee -a $LOG_FILE
sudo logrotate -d $CONFIG_FILE 2>&1 | grep "error" | tee -a $LOG_FILE
else
echo "配置文件语法检查通过" | tee -a $LOG_FILE
fi
# 检查最近轮转的日志
echo -e "\n最近轮转的日志:" | tee -a $LOG_FILE
sudo grep "rotating" /var/lib/logrotate/status | tail -10 | tee -a $LOG_FILE
# 检查日志文件大小
echo -e "\n大型日志文件 (>100M):" | tee -a $LOG_FILE
find /var/log -name "*.log" -size +100M -exec ls -lh {} \; 2>/dev/null | tee -a $LOG_FILE
echo -e "\n监控完成" | tee -a $LOG_FILE
2. 日志文件分析脚本
#!/bin/bash
# /usr/local/bin/analyze-logfiles.sh
LOG_DIR="/var/log"
REPORT_FILE="/tmp/log-analysis-$(date +%Y%m%d).txt"
echo "日志文件分析报告 - $(date)" > $REPORT_FILE
echo "=================================" >> $REPORT_FILE
# 分析日志文件数量和大小
echo -e "\n1. 日志文件统计:" >> $REPORT_FILE
find $LOG_DIR -name "*.log" -type f | wc -l | xargs echo "日志文件总数: " >> $REPORT_FILE
find $LOG_DIR -name "*.log" -type f -exec du -ch {} + | tail -1 | xargs echo "日志文件总大小: " >> $REPORT_FILE
# 列出最大的10个日志文件
echo -e "\n2. 最大的10个日志文件:" >> $REPORT_FILE
find $LOG_DIR -name "*.log" -type f -exec du -h {} + | sort -rh | head -10 >> $REPORT_FILE
# 检查轮转文件
echo -e "\n3. 轮转日志文件统计:" >> $REPORT_FILE
find $LOG_DIR -name "*.gz" -type f | wc -l | xargs echo "压缩的轮转日志数量: " >> $REPORT_FILE
echo -e "\n报告已保存到: $REPORT_FILE"
实用技巧
- 使用
logrotate -d 测试配置而不实际执行
- 结合
cron 和 anacron 确保日志轮转可靠执行
- 使用
dateext 和 dateformat 方便日志文件管理
- 为重要服务配置
prerotate 和 postrotate 脚本
- 定期检查
/var/lib/logrotate/status 文件了解轮转状态