nosharedscripts使logrotate对每个匹配日志文件独立执行prerotate/postrotate脚本,支持基于$1路径做差异化预处理,适用于多应用定制化日志管理。

Logrotate 默认使用 sharedscripts,即所有匹配的日志文件轮转完成后,postrotate 或 prerotate 脚本只执行一次。而 nosharedscripts 的作用正好相反:它让每个日志文件在轮转前/后都独立执行一遍脚本块——这正是为不同应用定制预处理流程的关键开关。
理解 nosharedscripts 的行为逻辑
启用 nosharedscripts 后,logrotate 会对配置块中每一个匹配到的日志路径(哪怕通配符匹配多个文件),分别触发一次 prerotate 和 postrotate。这意味着:
- 脚本内可通过
$1直接获取当前正在被处理的具体日志文件路径 - 可基于文件名、路径、所属服务动态判断执行动作,比如区分 access.log 和 error.log
- 避免了 sharedscripts 下需手动遍历
$@或解析状态的复杂性 - 适合需要“按文件粒度”做权限校验、内容检查、临时备份等预处理的场景
为 Nginx 定制 prerotate 预处理示例
假设你希望在每次轮转前检查 Nginx 日志是否可读、是否被其他进程占用,并记录操作上下文:
/var/log/nginx/*.log {
daily
rotate 30
dateext
compress
missingok
notifempty
create 0644 nginx nginx
nosharedscripts
prerotate
# $1 是当前待轮转的完整路径,如 /var/log/nginx/access.log
logger -t logrotate-ng "Prerotate start for $1"
if [ ! -r "$1" ]; then
logger -t logrotate-ng "ERROR: $1 is not readable, skipping"
exit 1
fi
# 检查是否有进程正写入该文件(非必须,但增强健壮性)
if lsof "$1" > /dev/null; then
logger -t logrotate-ng "WARN: $1 is still open by process, proceeding anyway"
fi
endscript
postrotate
# 发送 USR1 信号仅针对当前实例(若多实例部署可进一步区分)
if [ "$(basename "$1")" = "access.log" ]; then
kill -USR1 $(cat /run/nginx.pid 2>/dev/null) 2>/dev/null || true
fi
endscript
}
为多个应用差异化预处理的实践要点
当同一台服务器运行 Nginx、Tomcat、自研服务时,可借助 nosharedscripts 实现真正的“一配置一策略”:
- 把各应用日志配置拆分到
/etc/logrotate.d/下独立文件(如nginx、tomcat、myapp),互不干扰 - 在每个配置中明确使用
nosharedscripts,确保prerotate只作用于本应用日志 - 预处理脚本中用
basename "$1"或dirname "$1"提取关键信息,例如:
– 若路径含/tomcat/logs/,则调用systemctl try-reload-or-restart tomcat
– 若是/opt/myapp/logs/app-*.log,则先执行/opt/myapp/bin/prelog.sh "$1" - 注意脚本退出码:prerotate 中
exit 1会中止当前文件轮转,但不影响其他文件(这是 nosharedscripts 的另一优势)
调试与验证方法
直接测试配置是否按预期触发单文件脚本:
- 用
logrotate -d -f /etc/logrotate.d/nginx查看 debug 输出,确认prerotate块是否对每个匹配文件都打印执行日志 - 在 prerotate 中加入
echo "$(date): $1" >> /tmp/prerotate-debug.log,手动触发后检查生成几行 - 检查
/var/lib/logrotate/status文件,确认各日志路径的最后轮转时间是否独立更新











