日志轮询策略

Nginx 日志轮询配置

使用 logrotate(系统级)

配置文件:/etc/logrotate.d/nginx

yaml 复制代码
/var/log/nginx/*.log {
    daily                    # 按天轮询
    missingok                # 如果日志文件不存在,忽略错误
    rotate 30               # 保留最近30份(即30天)
    compress                 # 压缩旧日志(gzip)
    delaycompress            # 延迟压缩(先保留一份未压缩的)
    notifempty               # 如果日志为空,不轮询
    create 0640 nginx adm    # 创建新日志文件,权限 0640
    sharedscripts            # 所有日志共享同一脚本
    postrotate               # 轮询后执行
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}
参数 说明 示例
daily 按天轮询 weekly(每周)、monthly(每月)
size 100M 按大小轮询 size 100Msize 1G
rotate 30 保留数量 保留30份历史文件
compress 压缩(gzip) 生成 .log.gz
delaycompress 延迟压缩 最新一份不压缩
copytruncate 截断模式 用于无法重启的进程
dateext 日期扩展名 文件名带日期
missingok 文件缺失不报错 -
notifempty 空文件跳过 -

常见轮询策略:

按天 + 按大小(推荐)

yaml 复制代码
/var/log/nginx/access.log {
    daily
    size 500M                # 如果某天超过500M也切割
    rotate 90                # 保留90天
    compress
    delaycompress
    dateext                  # 文件名带日期:access.log-20250429.gz
    dateformat -%Y%m%d       # 日期格式
    missingok
    notifempty
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

按小时(高流量场景)

yaml 复制代码
/var/log/nginx/access.log {
    hourly                   # 每小时切分
    rotate 168               # 保留7天(24x7)
    compress
    delaycompress
    dateext
    dateformat -%Y%m%d%H     # 小时级:access.log-2025042914.gz
    missingok
    postrotate
        [ -f /var/run/nginx.pid ] && kill -USR1 `cat /var/run/nginx.pid`
    endscript
}

Nginx 自带配置方式

yaml 复制代码
# nginx.conf
http {
    # 自定义日志格式
    log_format main '$remote_addr - $remote_user [$time_local] "$request" '
                    '$status $body_bytes_sent "$http_referer" '
                    '"$http_user_agent" "$http_x_forwarded_for"';
    
    # 按天动态日志(需要 cron 配合清理)
    access_log /var/log/nginx/access.log main;
    error_log /var/log/nginx/error.log warn;
    
    # 或者使用日期变量(需要写脚本清理)
    # access_log /var/log/nginx/access-$year$month$day.log main;
}

Java/Spring Boot 日志轮询

Spring Boot 默认配置(Logback)

yaml 复制代码
logging:
  file:
    path: /var/log/myapp          # 日志目录
    name: app.log                 # 日志文件名(如果设置了 path,则自动拼接)
  
  # 日志格式
  pattern:
    file: "%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | [%thread] | %logger{36} | %msg%n"
    console: "%d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n"
  
  # 日志级别
  level:
    root: WARN
    com.mycompany: INFO
    org.springframework: WARN
    com.zaxxer.hikari: DEBUG
  
  # 日志轮询配置(关键部分!)
  logback:
    rollingpolicy:
      # 基于文件大小
      max-file-size: 100MB        # 每个文件最大 100MB
      
      # 基于时间
      file-name-pattern: ${LOG_FILE}.%d{yyyy-MM-dd}.%i.gz  # 文件名模板
      
      # 保留策略
      max-history: 30             # 保留最近 30 份历史文件
      total-size-cap: 3GB         # 所有归档文件总大小不超过 3GB
      
      # 清理策略
      clean-history-on-start: false  # 启动时不清除历史日志

实际生成文件:

/var/log/myapp/

├── app.log # 当前日志(最新)

├── app.log.2026-04-28.0.gz # 4月28日第一份压缩

├── app.log.2026-04-28.1.gz # 4月28日第二份压缩

├── app.log.2026-04-27.0.gz # 4月27日压缩

└── app.log.2026-04-26.0.gz # 4月26日压缩(30天后自动删除)

自定义 Logback 配置(更精细控制)

创建 logback-spring.xml 放在 src/main/resources:

csharp 复制代码
<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <!-- 日志目录 -->
    <property name="LOG_PATH" value="/var/log/myapp" />
    <property name="APP_NAME" value="myapp" />
    
    <!-- 控制台输出 -->
    <appender name="CONSOLE" class="ch.qos.logback.core.ConsoleAppender">
        <encoder>
            <pattern>%d{HH:mm:ss.SSS} %-5level [%thread] %logger{36} - %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 文件输出 + 轮询(基于时间) -->
    <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <!-- 当前日志文件 -->
        <file>${LOG_PATH}/${APP_NAME}.log</file>
        
        <!-- 轮询策略:基于时间和大小 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedRollingPolicy">
            <!-- 文件名模板 -->
            <fileNamePattern>${LOG_PATH}/${APP_NAME}.%d{yyyy-MM-dd}.%i.gz</fileNamePattern>
            
            <!-- 每个文件最大 100MB -->
            <maxFileSize>100MB</maxFileSize>
            
            <!-- 保留最近 30 天 -->
            <maxHistory>30</maxHistory>
            
            <!-- 所有归档文件总大小 -->
            <totalSizeCap>3GB</totalSizeCap>
        </rollingPolicy>
        
        <!-- 编码器 -->
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | [%thread] | %logger{36} | %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 独立错误日志(只记 ERROR 级别) -->
    <appender name="ERROR_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${LOG_PATH}/error.log</file>
        <!-- 只记录 ERROR 级别 -->
        <filter class="ch.qos.logback.classic.filter.ThresholdFilter">
            <level>ERROR</level>
        </filter>
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${LOG_PATH}/error.%d{yyyy-MM-dd}.gz</fileNamePattern>
            <maxHistory>60</maxHistory>         <!-- 错误日志保留 60 天 -->
        </rollingPolicy>
        <encoder>
            <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | [%thread] | %logger{36} | %msg%n</pattern>
        </encoder>
    </appender>
    
    <!-- 异步日志(提升性能) -->
    <appender name="ASYNC_FILE" class="ch.qos.logback.classic.AsyncAppender">
        <appender-ref ref="FILE" />
        <queueSize>1024</queueSize>             <!-- 队列大小 -->
        <discardingThreshold>0</discardingThreshold>  <!-- 是否丢弃日志 -->
        <includeCallerData>false</includeCallerData>
    </appender>
    
    <!-- 特殊业务日志(按模块分类) -->
    <logger name="com.myapp.order" level="INFO">
        <appender name="ORDER_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <file>${LOG_PATH}/order.log</file>
            <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                <fileNamePattern>${LOG_PATH}/order.%d{yyyy-MM-dd}.gz</fileNamePattern>
                <maxHistory>90</maxHistory>
            </rollingPolicy>
            <encoder>
                <pattern>%d{yyyy-MM-dd HH:mm:ss.SSS} | %-5level | %msg%n</pattern>
            </encoder>
        </appender>
    </logger>
    
    <!-- 根日志级别 -->
    <root level="INFO">
        <appender-ref ref="CONSOLE" />
        <appender-ref ref="ASYNC_FILE" />
        <appender-ref ref="ERROR_FILE" />
    </root>
</configuration>

关键配置:

配置项 作用 场景
SizeAndTimeBasedRollingPolicy 同时基于时间+大小 高流量应用
TimeBasedRollingPolicy 仅基于时间 常规应用
maxFileSize 单文件最大大小 避免单文件过大
maxHistory 保留历史文件天数 存储空间限制
totalSizeCap 归档文件总大小上限 磁盘空间保障
asyncAppender 异步写入 高并发场景

使用 logrotate 管理 Java 日志

csharp 复制代码
# /etc/logrotate.d/myapp-java
/var/log/myapp/*.log {
    daily
    missingok
    rotate 30
    compress
    delaycompress
    notifempty
    copytruncate                # Java 应用无需重启,直接截断
    dateext
    size 100M                   # 超过 100M 也切割
    postrotate
        # 可选:通知 Java 应用重新打开日志
        # kill -HUP `cat /var/run/myapp.pid`
    endscript
}

Java 应用使用 copytruncate 模式,不需要重启应用。这和 Nginx 不同(Nginx 需要 kill -USR1)。

日志策略对比

策略 Nginx Spring Boot默认 自定义 Logback logrotate
按天 ✅ 需logrotate ✅ 自动 ✅ 配置 ✅ 标准
按时 ✅ 需logrotate ❌ 不直接支持 ✅ 配置 ✅ 标准
按大小 ✅ 需logrotate ✅ 自动 ✅ 配置 ✅ 标准
压缩 ✅ 自动 ✅ 自动(gz) ✅ 自动 ✅ 自动
保留天数 ✅ logrotate设置 ✅ max-history ✅ maxHistory ✅ rotate设置
总大小限制 ✅ total-size-cap ✅ totalSizeCap
异步写入 ✅ asyncAppender
模块化 ✅ 多文件 ❌ 单文件 ✅ 多文件 ✅ 多文件
应用重启 ✅ 需信号 ❌ 不需要 ❌ 不需要 ❌ copytruncate

常用命令:

csharp 复制代码
# 查看 logrotate 状态
cat /var/lib/logrotate/status

# 手动执行轮询(debug模式)
logrotate -d /etc/logrotate.d/nginx

# 强制轮询(立即执行)
logrotate -f /etc/logrotate.d/nginx

# 查看日志目录大小
du -sh /var/log/nginx/
du -sh /var/log/myapp/

# 查看归档文件
ls -lh /var/log/nginx/*.gz
ls -lh /var/log/myapp/*.gz

# 解压查看历史日志
zcat /var/log/nginx/access.log-20250428.gz | tail -100

# 在压缩文件中搜索
zgrep "ERROR" /var/log/myapp/app.log.*.gz

日志轮询不是为了轮询而轮询,而是为了:

防止磁盘爆满(最紧急)

便于历史查询(时间范围清晰)

节省存储空间(压缩 + 自动清理)

问题排查方便(单个文件大小可控)

相关推荐
星融元asterfusion3 小时前
如何为您的网络选择正确的PTP配置文件:一份实用指南
网络·ptp·时间同步
Yoyo25年秋招冲冲冲3 小时前
【亲测可用】ubuntu系统下安装Openclaw+配置飞书
linux·ubuntu·ai·飞书·openclaw
你好,帅哥3 小时前
openssl ,msys2 ,交叉编译
linux·运维·服务器
光路科技3 小时前
一文讲透DHCP Snooping:从原理到工业网络实践
网络
计算机安禾3 小时前
【Linux从入门到精通】第36篇:DNS服务探秘——自己搭建一个内网DNS
linux·运维·servlet
2023自学中3 小时前
make clean 与 make distclean
linux·嵌入式
威联通安全存储4 小时前
穿透宿主机内核:QNAP Virtualization Station 硬件直通解析
网络·nas
BenD-_-4 小时前
CVE-2026-31431 Copy Fail:Linux 内核本地提权漏洞风险与缓解
linux·网络·安全
Web极客码4 小时前
2026年Linux VPS安全加固清单:SSH、防火墙与审计就绪配置
运维·服务器·数据库