1. 日志轮转系统设计原理
日志轮转(Log Rotation)是服务器运维中的基础但关键的技术,它能有效解决日志文件无限增长带来的各种问题。我在管理生产环境服务器时,曾遇到过单个日志文件涨到50GB导致磁盘爆满的紧急情况,从那以后就深刻认识到自动化日志管理的重要性。
1.1 为什么需要日志轮转
当应用程序持续运行时,日志文件会像滚雪球一样越来越大。这会导致三个主要问题:
- 磁盘空间占用:一个失控的日志文件可以轻易占满整个磁盘分区
- 性能影响:大文件会降低grep等日志分析工具的效率
- 管理困难:单个大文件难以归档、备份和转移
通过日志轮转,我们可以:
- 按大小或时间自动分割日志
- 压缩旧日志节省空间
- 自动清理过期的历史日志
- 保持当前日志文件大小可控
1.2 常见轮转策略对比
在实际运维中,主要有两种日志轮转策略:
| 策略类型 | 触发条件 | 适用场景 | 优缺点 |
|---|---|---|---|
| 按大小轮转 | 当日志文件达到指定大小时 | 高频日志应用 | 实时性好但可能产生大量小文件 |
| 按时间轮转 | 按固定时间间隔(天/周/月) | 低频稳定日志 | 管理简单但不够实时 |
提示:生产环境中通常采用混合策略,同时设置大小和时间阈值,任一条件满足即触发轮转。
需要模型API调用? 免费领10W Token,多模型网关一键接入 Claude、DeepSeek 等主流模型。
2. 基础日志轮转实现
2.1 按大小轮转的核心逻辑
实现按大小轮转的关键是检测文件大小并执行轮转操作。以下是基础实现步骤:
bash复制#!/bin/bash
# 基础日志轮转脚本
LOG_FILE="/var/log/myapp.log"
MAX_SIZE="10M" # 10MB
BACKUP_DIR="/var/log/backups"
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 检查日志文件大小
current_size=$(du -b "$LOG_FILE" | cut -f1)
max_size_bytes=$(numfmt --from=iec "$MAX_SIZE")
if [ "$current_size" -gt "$max_size_bytes" ]; then
# 生成带时间戳的备份文件名
backup_name="myapp_$(date +%Y%m%d_%H%M%S).log"
# 执行轮转
cp "$LOG_FILE" "$BACKUP_DIR/$backup_name"
> "$LOG_FILE" # 清空原日志文件
# 可选:压缩备份
gzip "$BACKUP_DIR/$backup_name"
fi
2.2 按时间轮转的实现
基于时间的轮转通常结合cron定时任务实现:
bash复制#!/bin/bash
# 每日日志轮转脚本
LOG_FILE="/var/log/myapp.log"
BACKUP_DIR="/var/log/backups"
RETENTION_DAYS=30 # 保留30天日志
# 创建备份目录
mkdir -p "$BACKUP_DIR"
# 生成备份文件名
backup_name="myapp_$(date +%Y%m%d).log"
# 执行轮转
cp "$LOG_FILE" "$BACKUP_DIR/$backup_name"
> "$LOG_FILE"
# 压缩备份
gzip "$BACKUP_DIR/$backup_name"
# 清理旧日志
find "$BACKUP_DIR" -name "myapp_*.log.gz" -mtime +$RETENTION_DAYS -delete
注意:直接清空日志文件可能会导致少量日志丢失。对于关键应用,应考虑使用logrotate的copytruncate模式或通知应用重新打开日志文件。
3. 高级日志管理技巧
3.1 使用logrotate工具
Linux系统自带的logrotate工具提供了更完善的日志轮转功能。配置文件示例:
code复制/var/log/myapp.log {
daily
rotate 30
compress
delaycompress
missingok
notifempty
create 0640 root adm
postrotate
/usr/bin/systemctl reload myapp >/dev/null
endscript
}
关键参数说明:
daily:每天轮转rotate 30:保留30个备份compress:使用gzip压缩delaycompress:延迟压缩前一个日志文件postrotate:轮转后执行的命令
3.2 多日志文件管理
实际项目中往往需要管理多个日志文件。使用关联数组可以优雅地实现:
bash复制#!/bin/bash
# 多日志文件轮转脚本
declare -A LOGS=(
["/var/log/myapp/app.log"]="10M"
["/var/log/myapp/error.log"]="5M"
["/var/log/myapp/debug.log"]="1M"
)
BACKUP_DIR="/var/log/backups"
RETENTION_DAYS=30
mkdir -p "$BACKUP_DIR"
for logfile in "${!LOGS[@]}"; do
max_size="${LOGS[$logfile]}"
current_size=$(du -b "$logfile" | cut -f1)
