logrotate不支持size与hourly的and逻辑,仅支持or触发;实现“每小时且≤100mb”需用prerotate脚本结合maxsize、状态文件时间戳与文件大小判断,满足任一条件才执行轮转。

Logrotate 本身不支持 size + hourly 的双重触发条件(即“达到指定大小或每小时轮转一次,满足任一即执行”),它的配置是单维度调度:要么按时间(hourly/daily/weekly),要么按大小(size),二者不能同时生效。但针对超高频日志(如秒级写入 MB 级别),需实现「每小时轮转,且单个日志文件不超过 100MB」的精准控制,可借助以下组合方案达成目标。
核心思路:用 hourly + maxsize + postrotate 配合外部判断
虽然 logrotate 不原生支持“size 或 hourly 任一满足即转”,但可通过 hourly 执行 + size 检查 + 条件性 rotate 的方式模拟。关键在于:让 logrotate 每小时运行时,先检查当前日志是否超限,仅在超限时才真正执行压缩/归档;否则跳过实际操作,避免空转。
配置示例(/etc/logrotate.d/highfreq-app)
注意:此方案依赖 cron 每小时调用 logrotate,且需启用 logrotate 的 -s 状态文件和 -f 强制模式(用于调试),生产环境建议用标准 hourly cron。
/var/log/app/access.log {
hourly
missingok
compress
delaycompress
compresscmd /bin/gzip
compressext .gz
maxsize 100M
create 0644 www-data www-data
sharedscripts
postrotate
# 只有当日志真实被 rotate 后才执行(logrotate 内部机制保证:仅当文件被重命名后才调用 postrotate)
# 若未达 maxsize 且未到 hourly 时间点(实际 hourly 已强制触发),此处不会运行 —— 但 hourly 下每次都会尝试 rotate
# 所以更稳妥做法:在 prerotate 中主动判断并退出
endscript
}
真正可靠的方案:prerotate + exit 0 控制(推荐)
利用 prerotate 脚本,在 logrotate 每次 hourly 执行前,检查当前日志大小。若未超限且距离上次 rotate 不足 1 小时,则主动退出,阻止本次 rotate:
- 确保系统已启用
/var/lib/logrotate/status状态文件(默认开启) - 在
prerotate中读取状态文件,解析该日志最后一次 rotate 时间 - 计算距今是否 ≥ 3600 秒;同时用
stat -c %s获取当前文件大小 - 若「未满 1 小时」且「未超 maxsize」,则
exit 0(logrotate 将跳过本次处理)
完整配置节示例:
/var/log/app/access.log {
hourly
missingok
compress
delaycompress
create 0644 www-data www-data
sharedscripts
<pre class="brush:php;toolbar:false;">prerotate
LOGFILE="/var/log/app/access.log"
STATUS_FILE="/var/lib/logrotate/status"
MAXSIZE=104857600 # 100MB
MIN_INTERVAL=3600
# 获取当前大小
if [ -f "$LOGFILE" ]; then
CUR_SIZE=$(stat -c "%s" "$LOGFILE" 2>/dev/null || echo 0)
else
CUR_SIZE=0
fi
# 解析上次 rotate 时间(格式如:"/var/log/app/access.log 2024-05-20-03:00:01")
LAST_ROTATE=$(awk -v pat="$LOGFILE" '$1 == pat {print $2; exit}' "$STATUS_FILE" 2>/dev/null)
if [ -n "$LAST_ROTATE" ]; then
# 转为秒时间戳(需 GNU date)
LAST_TS=$(date -d "$LAST_ROTATE" +%s 2>/dev/null || echo 0)
NOW_TS=$(date +%s)
ELAPSED=$((NOW_TS - LAST_TS))
else
ELAPSED=$MIN_INTERVAL # 首次运行视为超时
fi
# 满足任一条件即继续:超时 或 超大小
if [ "$ELAPSED" -ge "$MIN_INTERVAL" ] || [ "$CUR_SIZE" -ge "$MAXSIZE" ]; then
exit 0
else
exit 1 # 阻止本次 rotate
fi
endscript
postrotate
# 可选:通知服务重新打开日志(如 nginx -s reopen,或 kill -USR1)
[ -f /var/run/app.pid ] && kill -USR1 $(cat /var/run/app.pid) 2>/dev/null || true
endscript}
配套要求与验证要点
-
cron 必须存在且正常运行 hourly 任务:确认
/etc/cron.hourly/logrotate存在且可执行,或系统级 cron 包含0 * * * * /usr/bin/logrotate /etc/logrotate.conf -
logrotate 版本 ≥ 3.8.0:早期版本 prerotate exit 1 行为不一致,建议用
logrotate --version核查 -
测试方法:手动运行
logrotate -d -f /etc/logrotate.conf(-d 查看调试输出,-f 强制),观察是否按预期跳过或执行 - 高频场景补充:若单小时内日志突增远超 100MB,maxsize 仍会触发中间轮转(logrotate 在 single run 中可多次 rotate 同一文件),因此该方案天然支持「一小时内多次按 size 切分」











