You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Log4j配置咨询:RollingFile日志滚动后执行脚本的实现方法

如何让Log4j在日志滚动完成后执行指定脚本?

当然可以实现!不管你用的是Log4j 1.x还是最新的Log4j 2,都有对应的方案来在日志滚动完成后触发自定义脚本,发送通知邮件、检索特定日志模式这类需求完全能搞定。下面分版本给你详细说明:


一、Log4j 2.x(推荐,功能更完善)

Log4j 2自带了PostRollupActions配置项,可以直接在滚动完成后执行自定义动作。你只需要两步:

1. 编写自定义执行脚本的Action类

实现Log4j 2的Action接口,在execute方法里调用你的脚本:

package com.yourcompany.log4j;

import org.apache.logging.log4j.core.appender.rolling.Action;
import org.apache.logging.log4j.core.config.plugins.Plugin;
import org.apache.logging.log4j.core.config.plugins.PluginAttribute;
import org.apache.logging.log4j.core.config.plugins.PluginFactory;

import java.io.IOException;

@Plugin(name = "RunScriptAction", category = "Core", elementType = "action", printObject = true)
public class RunScriptAction implements Action {

    private final String scriptPath;

    private RunScriptAction(String scriptPath) {
        this.scriptPath = scriptPath;
    }

    @PluginFactory
    public static RunScriptAction create(@PluginAttribute("scriptPath") String scriptPath) {
        return new RunScriptAction(scriptPath);
    }

    @Override
    public boolean execute() throws IOException {
        // 执行脚本,可传递滚动后的日志文件路径作为参数
        ProcessBuilder pb = new ProcessBuilder("/bin/bash", scriptPath);
        // 如果你需要把滚动后的日志文件名传给脚本,可添加参数:
        // pb.command().add(getLatestRolledLogFile()); // 需额外实现获取日志文件名的逻辑
        pb.inheritIO();
        Process process = pb.start();
        
        try {
            process.waitFor();
        } catch (InterruptedException e) {
            Thread.currentThread().interrupt();
            return false;
        }
        return process.exitValue() == 0;
    }

    @Override
    public void close() {
        // 无资源需释放则留空
    }
}

2. 在Log4j 2配置文件中引用这个Action

以XML配置为例,在RollingFile节点下添加PostRollupActions:

<Configuration status="INFO">
  <Appenders>
    <RollingFile name="RollingFile" fileName="logs/app.log"
                 filePattern="logs/app-%d{yyyy-MM-dd}-%i.log.gz">
      <PatternLayout pattern="%d %p %c{1.} [%t] %m%n"/>
      <SizeBasedTriggeringPolicy size="10 MB"/>
      <!-- 滚动完成后执行自定义脚本动作 -->
      <PostRollupActions>
        <RunScriptAction scriptPath="/path/to/your/post-rollup-script.sh"/>
      </PostRollupActions>
    </RollingFile>
  </Appenders>
  <Loggers>
    <Root level="info">
      <AppenderRef ref="RollingFile"/>
    </Root>
  </Loggers>
</Configuration>

二、Log4j 1.x(旧版本兼容方案)

Log4j 1.x没有内置的滚动后动作触发机制,但可以通过扩展RollingFileAppender来实现:

1. 扩展RollingFileAppender并重写rollOver方法

import org.apache.log4j.RollingFileAppender;
import org.apache.log4j.spi.ErrorHandler;

public class ScriptTriggerRollingAppender extends RollingFileAppender {

    private String scriptPath;

    public void setScriptPath(String scriptPath) {
        this.scriptPath = scriptPath;
    }

    @Override
    public void rollOver() {
        // 先执行默认的日志滚动逻辑
        super.rollOver();
        
        // 滚动完成后执行脚本
        try {
            ProcessBuilder pb = new ProcessBuilder("/bin/bash", scriptPath);
            pb.inheritIO();
            Process process = pb.start();
            process.waitFor();
        } catch (Exception e) {
            // 脚本执行失败时记录错误,不影响日志系统运行
            ErrorHandler errorHandler = this.getErrorHandler();
            if (errorHandler != null) {
                errorHandler.error("Failed to run post-rollover script", e, 0);
            }
        }
    }
}

2. 在Log4j 1.x的properties配置中使用自定义Appender

log4j.rootLogger=INFO, ROLLING

# 配置自定义滚动Appender
log4j.appender.ROLLING=com.yourcompany.log4j.ScriptTriggerRollingAppender
log4j.appender.ROLLING.File=logs/app.log
log4j.appender.ROLLING.MaxFileSize=10MB
log4j.appender.ROLLING.MaxBackupIndex=10
log4j.appender.ROLLING.layout=org.apache.log4j.PatternLayout
log4j.appender.ROLLING.layout.ConversionPattern=%d %p %c{1} - %m%n
# 指定要执行的脚本路径
log4j.appender.ROLLING.scriptPath=/path/to/your/post-rollup-script.sh

几个关键注意事项

  • 权限问题:运行Java进程的用户需要有脚本的执行权限,以及脚本中涉及操作的权限(比如读取日志文件、发送邮件的权限)。
  • 脚本参数传递:如果脚本需要知道滚动后的日志文件名,可以在自定义Action/Appender中获取滚动后的文件路径,作为参数传给脚本。
  • 异常隔离:脚本执行失败不要影响日志系统的正常运行,一定要捕获并记录异常,避免整个日志服务崩溃。
  • 脚本示例:你可以在脚本里实现这些逻辑,比如发送邮件:
    #!/bin/bash
    # 发送滚动完成通知
    echo "日志已滚动完成:$1" | mail -s "Log Rollover Notification" your-email@example.com
    # 检索日志中的错误模式
    grep "ERROR" $1 >> /logs/error-summary.log
    

内容的提问来源于stack exchange,提问作者MHoop

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 04:32:48