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
相关产品推荐
相关产品推荐

