Tomcat8中如何将System.out输出重定向至其他文件?
解决Tomcat 8中System.out输出无法重定向的问题
我之前也碰到过Tomcat 8强制把System.out输出写到tomcat8-stdout.log的情况,你试过的两种方法没生效,大概率是因为Tomcat自身有一套System.out/err的捕获机制,优先级比log4j和java.util.logging更高。下面给你几个可行的解决方案:
方法1:禁用Tomcat对System.out的捕获机制
Tomcat 8默认会启动一个捕获器把System.out/err的内容转写到stdout.log,你需要先关掉这个功能:
- 找到Tomcat目录下的
bin/catalina.sh(Linux/macOS)或者catalina.bat(Windows) - 在文件开头的JVM参数配置部分,添加如下参数:
# Linux/macOS CATALINA_OPTS="$CATALINA_OPTS -Dorg.apache.catalina.core.SystemOutAndErrCapture.enabled=false" # Windows set CATALINA_OPTS=%CATALINA_OPTS% -Dorg.apache.catalina.core.SystemOutAndErrCapture.enabled=false - 重启Tomcat,这时候Tomcat就不会再拦截System.out的输出了,你的log4j配置应该就能生效。
方法2:确保log4j正确桥接System.out
如果禁用Tomcat的捕获后,log4j还是没拿到输出,你可以手动把System.out桥接到log4j的Logger:
- 如果用的是Log4j 1.x,在应用启动时添加这段初始化代码:
import org.apache.log4j.Logger; import org.apache.log4j.PatternLayout; import org.apache.log4j.RollingFileAppender; import org.apache.log4j.Level; import java.io.PrintStream; import java.io.OutputStream; public class SysOutRedirector { public static void init() { Logger sysOutLogger = Logger.getLogger("SystemOut"); RollingFileAppender appender = new RollingFileAppender(); appender.setFile("/path/to/your/target/log.log"); appender.setLayout(new PatternLayout("%d{ISO8601} %-5p %c{1}:%L - %m%n")); appender.setMaxFileSize("10MB"); appender.setMaxBackupIndex(5); appender.activateOptions(); sysOutLogger.addAppender(appender); // 重定向System.out/err到Logger System.setOut(new PrintStream(new Log4jOutputStream(sysOutLogger, Level.INFO))); System.setErr(new PrintStream(new Log4jOutputStream(sysOutLogger, Level.ERROR))); } // 自定义输出流,将内容传给log4j private static class Log4jOutputStream extends OutputStream { private final Logger logger; private final Level level; private final StringBuilder buffer = new StringBuilder(); public Log4jOutputStream(Logger logger, Level level) { this.logger = logger; this.level = level; } @Override public void write(int b) { if (b == '\n') { logger.log(level, buffer.toString()); buffer.setLength(0); } else { buffer.append((char) b); } } } } - 如果用的是Log4j 2.x,可以直接使用官方桥接器:
- 在Maven依赖中添加:
<dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-core</artifactId> <version>2.20.0</version> </dependency> <dependency> <groupId>org.apache.logging.log4j</groupId> <artifactId>log4j-jul</artifactId> <version>2.20.0</version> </dependency> - 在JVM参数中添加
-Djava.util.logging.manager=org.apache.logging.log4j.jul.LogManager,让JUL使用Log4j的管理器 - 在log4j2.xml中配置好你的RollingFileAppender即可
- 在Maven依赖中添加:
方法3:避免Tomcat日志组件冲突
有时候Tomcat自带的日志组件会和应用的log4j冲突,你可以:
- 打开Tomcat的
conf/context.xml,在<Context>标签内添加:
这个配置让web应用优先加载自己的日志库,避免Tomcat自带的JUL组件干扰<Loader delegate="false"/> - 确保你的web应用
WEB-INF/lib下只包含你需要的log4j相关jar包,不要混入Tomcat自带的日志jar
做完这些步骤后,重启Tomcat再测试,应该就能把System.out的输出重定向到你指定的日志文件了。
内容的提问来源于stack exchange,提问作者Neel
相关产品推荐
相关产品推荐

