日志轮询策略

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

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

防止磁盘爆满(最紧急)

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

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

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

相关推荐
AlfredZhao3 小时前
vi 删除指定范围的行,不用再反复按 dd
linux·vi
用户9718356334669 小时前
银河麒麟 KY10 申威(SW64) 安装 nginx-1.16.1-2.p01.ky10.sw_64.rpm 详细步骤
linux
猪脚踏浪11 小时前
linux 拷贝文件或目录到指定的位置
linux
大树881 天前
金刚石散热越强,管路越先见顶
大数据·运维·服务器·人工智能·ai
摇滚侠1 天前
Linux CentOS7 rpm 安装 MySQL 5.7
linux·运维·mysql
bush41 天前
嵌入式linux学习记录十四、术语
linux·嵌入式
载数而行5201 天前
Linux 11 动态监控指令top
linux
小宇宙Zz1 天前
Maven依赖冲突
java·服务器·maven
网络研究院1 天前
2026年网络安全
网络·安全·法律·法规·趋势·发展
酣大智1 天前
ARP代理--工作原理
运维·网络·arp·arp代理