Tomcat多Web应用中Log4j2配置文件日志输出异常排查
Tomcat多Web应用Log4j2日志异常问题
问题现象
在Tomcat中部署2个Web应用,各自拥有独立的Log4j2 Properties配置文件,但每个应用本地和Tomcat的lib目录都放置了log4j-api-2.18.0.jar和log4j-core-2.18.0.jar,出现以下异常:
- 第二个应用的日志要么写入第一个应用的日志文件,要么仅输出到控制台,无法写入自身指定文件
- 其中一份CMS配置的日志只输出到控制台,不写入文件
- 另一份CMS配置的日志会写入会计应用的
accounting.log,而非自身的cms_config.log
核心原因
- 类加载冲突:Tomcat的lib目录和应用WEB-INF/lib重复放置Log4j2核心包,导致Log4j2核心类被Tomcat公共类加载器加载,多个应用共享同一个Log4j2上下文,日志配置互相覆盖。
- Appender名称重复:第二份CMS配置和会计应用的配置都使用
fileLogger作为RollingFileAppender的名称,共享上下文时后启动应用会复用先启动应用的同名Appender,导致日志写入错误文件。 - 第一份CMS配置语法错误:
- 存在无效的空配置行
appender.cmsConfig.filter=,导致Appender初始化失败 logger.cms_config.appenderRefs仅指定cmsConfig,但后续又添加了console的appenderRef,配置逻辑冲突
- 存在无效的空配置行
修复步骤
1. 清理重复的Log4j2包
- 删除Tomcat/lib目录下的
log4j-api-2.18.0.jar和log4j-core-2.18.0.jar - 仅保留每个应用
WEB-INF/lib目录下的这两个包,让每个应用使用独立类加载器加载Log4j2,实现日志上下文隔离
2. 修正第一份CMS配置的语法错误
修改后的完整配置:
# Extra logging related to initialization of Log4j # Set to debug or trace if log4j initialization is failing status = debug # Name of the configuration name= CMS-Config # Log files location property.basePath = ${sys:catalina.home}/logs appenders = cmsConfig, console # RollingFileAppender name, pattern, path and rollover policy appender.cmsConfig.type = RollingFile appender.cmsConfig.name = cmsConfig_Logger appender.cmsConfig.createOnDemand = true appender.cmsConfig.fileName= ${basePath}/cms_config.log appender.cmsConfig.filePattern= ${basePath}/app_%d{yyyyMMdd}.log.gz appender.cmsConfig.layout.type = PatternLayout appender.cmsConfig.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%l] - %msg%n appender.cmsConfig.policies.type = Policies # RollingFileAppender rotation policy appender.cmsConfig.policies.startup.type = OnStartupTriggeringPolicy appender.cmsConfig.policies.size.type = SizeBasedTriggeringPolicy appender.cmsConfig.policies.size.size = 50MB appender.cmsConfig.policies.time.type = TimeBasedTriggeringPolicy appender.cmsConfig.policies.time.interval = 1 appender.cmsConfig.policies.time.modulate = true appender.cmsConfig.strategy.type = DefaultRolloverStrategy appender.cmsConfig.strategy.delete.type = Delete appender.cmsConfig.strategy.delete.basePath = ${basePath} appender.cmsConfig.strategy.delete.maxDepth = 10 appender.cmsConfig.strategy.delete.ifLastModified.type = IfLastModified # Delete all files older than 3 days appender.cmsConfig.strategy.delete.ifLastModified.age = 3d # Console appender configuration appender.console.type = Console appender.console.name = consoleLogger appender.console.layout.type = PatternLayout appender.console.layout.pattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss} %highlight{%level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green, DEBUG=blue} %c{1}:%L - %m%n loggers = cms_config # Classes in this package or sub packages will use ConsoleAppender and RollingFileAppender for logging logger.cms_config.name = com.dancik.cms logger.cms_config.level = ERROR logger.cms_config.additivity = false logger.cms_config.appenderRefs = cmsConfig, console logger.cms_config.appenderRef.cmsConfig.ref = cmsConfig_Logger logger.cms_config.appenderRef.cmsConfig.level = ERROR logger.cms_config.appenderRef.console.ref = consoleLogger # Root logger level rootLogger.level = debug rootLogger.additivity = false # Root logger referring to console appender rootLogger.appenderRef.rolling.ref = cmsConfig_Logger rootLogger.appenderRef.stdout.ref = consoleLogger
修改点:
- 删除无效的
appender.cmsConfig.filter=配置行 - 将
logger.cms_config.appenderRefs改为cmsConfig, console,与后续的appenderRef配置匹配
3. 修改第二份CMS配置的Appender名称
避免与会计应用的Appender名称重复,修改后的完整配置:
# Extra logging related to initialization of Log4j # Set to debug or trace if log4j initialization is failing status = ERROR # Name of the configuration name= CMS-Config # Log files location property.basePath = ${sys:catalina.home}/logs # RollingFileAppender name, pattern, path and rollover policy appender.cmsRolling.type = RollingFile appender.cmsRolling.name = cmsFileLogger appender.cmsRolling.createOnDemand = true appender.cmsRolling.fileName= ${basePath}/cms_config.log appender.cmsRolling.filePattern= ${basePath}/app_%d{yyyyMMdd}.log.gz appender.cmsRolling.layout.type = PatternLayout appender.cmsRolling.layout.pattern = %d{yyyy-MM-dd HH:mm:ss.SSS} %level [%t] [%l] - %msg%n appender.cmsRolling.policies.type = Policies # RollingFileAppender rotation policy appender.cmsRolling.policies.size.type = SizeBasedTriggeringPolicy appender.cmsRolling.policies.size.size = 50MB appender.cmsRolling.policies.time.type = TimeBasedTriggeringPolicy appender.cmsRolling.policies.time.interval = 1 appender.cmsRolling.policies.time.modulate = true appender.cmsRolling.strategy.type = DefaultRolloverStrategy appender.cmsRolling.strategy.delete.type = Delete appender.cmsRolling.strategy.delete.basePath = ${basePath} appender.cmsRolling.strategy.delete.maxDepth = 10 appender.cmsRolling.strategy.delete.ifLastModified.type = IfLastModified # Delete all files older than 3 days appender.cmsRolling.strategy.delete.ifLastModified.age = 3d # Console appender configuration appender.console.type = Console appender.console.name = consoleLogger appender.console.layout.type = PatternLayout appender.console.layout.pattern = [%-5p] %d{yyyy-MM-dd HH:mm:ss} %highlight{%level}{FATAL=bg_red, ERROR=red, WARN=yellow, INFO=green, DEBUG=blue} %c{1}:%L - %m%n # Root logger level rootLogger.level = ERROR # Root logger referring to console appender rootLogger.appenderRef.stdout.ref = consoleLogger rootLogger.appenderRef.rolling.ref = cmsFileLogger
修改点:
- 将Appender前缀从
rolling改为cmsRolling - 将Appender名称从
fileLogger改为cmsFileLogger - 同步修改rootLogger中对应的appenderRef引用
4. 验证配置
重启Tomcat后,检查两个应用的日志是否分别写入各自指定的文件,CMS应用日志是否同时输出到控制台和文件(符合配置逻辑)。
内容的提问来源于stack exchange,提问作者balloffire
相关产品推荐
相关产品推荐

