[日志管理] 启动程序时,因报“log4j-slf4j-impl cannot be present with log4j-to-slf4j”错误而导致程序终止运行[转发]
Posted 千千寰宇
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[日志管理] 启动程序时,因报“log4j-slf4j-impl cannot be present with log4j-to-slf4j”错误而导致程序终止运行[转发]相关的知识,希望对你有一定的参考价值。
此错误出现过了几次了,有必要记录一下。
1 问题描述
运行测试用例的spring-boot Java程序片段时,报如下错误:
SLF4J: Class path contains multiple SLF4J bindings.
SLF4J: Found binding in [jar:file:/D:/Program_Data/maven_repository/org/apache/logging/log4j/log4j-slf4j-impl/2.13.3/log4j-slf4j-impl-2.13.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: Found binding in [jar:file:/D:/Program_Data/maven_repository/ch/qos/logback/logback-classic/1.2.3/logback-classic-1.2.3.jar!/org/slf4j/impl/StaticLoggerBinder.class]
SLF4J: See http://www.slf4j.org/codes.html#multiple_bindings for an explanation.
SLF4J: Actual binding is of type [org.apache.logging.slf4j.Log4jLoggerFactory]
java.lang.ExceptionInInitializerError
at sun.reflect.NativeConstructorAccessorImpl.newInstance0(Native Method)
at sun.reflect.NativeConstructorAccessorImpl.newInstance(NativeConstructorAccessorImpl.java:62)
at sun.reflect.DelegatingConstructorAccessorImpl.newInstance(DelegatingConstructorAccessorImpl.java:45)
at java.lang.reflect.Constructor.newInstance(Constructor.java:423)
at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:250)
at org.junit.runners.BlockJUnit4ClassRunner.createTest(BlockJUnit4ClassRunner.java:260)
at org.junit.runners.BlockJUnit4ClassRunner$2.runReflectiveCall(BlockJUnit4ClassRunner.java:309)
at org.junit.internal.runners.model.ReflectiveCallable.run(ReflectiveCallable.java:12)
at org.junit.runners.BlockJUnit4ClassRunner.methodBlock(BlockJUnit4ClassRunner.java:306)
at org.junit.runners.BlockJUnit4ClassRunner$1.evaluate(BlockJUnit4ClassRunner.java:100)
at org.junit.runners.ParentRunner.runLeaf(ParentRunner.java:366)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:103)
at org.junit.runners.BlockJUnit4ClassRunner.runChild(BlockJUnit4ClassRunner.java:63)
at org.junit.runners.ParentRunner$4.run(ParentRunner.java:331)
at org.junit.runners.ParentRunner$1.schedule(ParentRunner.java:79)
at org.junit.runners.ParentRunner.runChildren(ParentRunner.java:329)
at org.junit.runners.ParentRunner.access$100(ParentRunner.java:66)
at org.junit.runners.ParentRunner$2.evaluate(ParentRunner.java:293)
at org.junit.runners.ParentRunner$3.evaluate(ParentRunner.java:306)
at org.junit.runners.ParentRunner.run(ParentRunner.java:413)
at org.junit.runner.JUnitCore.run(JUnitCore.java:137)
at com.intellij.junit4.JUnit4IdeaTestRunner.startRunnerWithArgs(JUnit4IdeaTestRunner.java:69)
at com.intellij.rt.junit.IdeaTestRunner$Repeater$1.execute(IdeaTestRunner.java:38)
at com.intellij.rt.execution.junit.TestsRepeater.repeat(TestsRepeater.java:11)
at com.intellij.rt.junit.IdeaTestRunner$Repeater.startRunnerWithArgs(IdeaTestRunner.java:35)
at com.intellij.rt.junit.JUnitStarter.prepareStreamsAndStart(JUnitStarter.java:235)
at com.intellij.rt.junit.JUnitStarter.main(JUnitStarter.java:54)
Caused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
at org.apache.logging.slf4j.Log4jLoggerFactory.validateContext(Log4jLoggerFactory.java:49)
at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:39)
at org.apache.logging.slf4j.Log4jLoggerFactory.newLogger(Log4jLoggerFactory.java:30)
at org.apache.logging.log4j.spi.AbstractLoggerAdapter.getLogger(AbstractLoggerAdapter.java:54)
at org.apache.logging.slf4j.Log4jLoggerFactory.getLogger(Log4jLoggerFactory.java:30)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:358)
at org.slf4j.LoggerFactory.getLogger(LoggerFactory.java:383)
at bugs.debug.ParseNettyHttpServerLog.<clinit>(ParseNettyHttpServerLog.java:25)
... 27 more
Process finished with exit code -1
2 问题分析
- 错误日志翻译:
Caused by: org.apache.logging.log4j.LoggingException: log4j-slf4j-impl cannot be present with log4j-to-slf4j
log4j-slf4j-impl 和 log4j-to-slf4j 这两个包不能同时存在。
- 那么为什么这两个包不能同时存在呢?
我们先来看一下这两个包的定义:
- log4j-slf4j-impl : 主要是 log4j 对
slf4j
接口的实现Apache Log4j SLF4J Binding: The Apache Log4j SLF4J API binding to Log4j 2 Core
- log4j-to-slf4j : slf4j 对 log4j 接口的适配
Apache Log4j to SLF4J Adapter: The Apache Log4j binding between Log4j 2 API and SLF4J
这两个接口不能同时存在的意思是说:
要么用 log4j 日志系统,然后同时支持 slf4j 接口的调用;
要么用其他日志系统,比如logback(logback是 slf4j 接口的实现),然后适配log4j接口。不能兼而有之!
spring boot
框架默认使用的logback
日志系统,logback
实现的是slf4j
接口。因此需要适配 log4j 接口,因而会引入log4j-to-slf4j
。
因此,如果您正在使用的是spring boot,则不能引入log4j-slf4j-impl。
问题解决思路:只需要看一下是哪个 pom 文件引入了 log4j-slf4j-impl,把这个包去掉就可以啦!
3 解决方法
- 本问题中,博主的工程确实是基于
spring-boot
框架,但博主采纳并使用的日志框架是slf4j
+log4j
即:需去除
spring-boot
自带的log4j-to-slf4j
依赖
<dependency>
<groupId>org.springframework.cloud</groupId>
<artifactId>spring-cloud-gateway-server</artifactId>
<scope>test</scope>
<exclusions>
<exclusion>
<artifactId>log4j-to-slf4j</artifactId>
<groupId>org.apache.logging.log4j</groupId>
</exclusion>
</exclusions>
</dependency>
X 参考文献

本文链接: https://www.cnblogs.com/johnnyzen
关于博文:评论和私信会在第一时间回复,或直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
日常交流:大数据与软件开发-QQ交流群: 774386015 【入群二维码】参见左下角。您的支持、鼓励是博主技术写作的重要动力!
Linux系统管理初步系统日志与screen程序
一、系统日志
系统日志是我们了解系统状况,服务启动情况,学会阅读日志是我们了解系统运行状况并进行管理的基本技能。
(一)/var/log/messages
系统中的各种操作都会记录到系统日志中,日志储存在/var/log/目录中,日志会被系统的logrotate程序自动切割,就是日志文件达到你设定的条件时,就自动结束,然后重新生成一个文件开始记录日志。
1、查看系统日志
tail /var/log/messages
确实可以记录下不少内容的
2、通过/logrotate.conf文件配置日志记录机制
cat /etc/logrotate.conf
把主要的内容列在这个
# rotate log files weekly
weekly 多久结束一次日志记录,每周还是每月、每天等等
# keep 4 weeks worth of backlogs
rotate 4 多少份替换掉最旧一份日志,就是你最多能保存几份日志文件,这里是4,就是说如果你有4份日志文件了那么再多出来的一份就会把第一份覆盖掉,就像监控中你最可以回放的录像天数。
# create new (empty) log files after rotating old ones
create
# use date as a suffix of the rotated file
dateext
# uncomment this if you want your log files compressed
#compress
# RPM packages drop log rotation information into this directory
include /etc/logrotate.d
可以把需要使用
# no packages own wtmp and btmp -- we‘ll rotate them here
这个语句下面可以把你要logrotate程序切割的日志文件的路径加进来,让程序自动帮你切割日志文件,常见的比如Nginx日志之类。
比如处理:
/usr/local/nginx/logs/*.log {
daily
dateext
compress
rotate 7
sharedscripts
postrotate
kill -USR1cat /var/run/nginx.pid
endscript
}
/var/log/wtmp {
monthly
create 0664 root utmp
minsize 1M
rotate 1
}
/var/log/btmp {
missingok
monthly
create 0600 root utmp
rotate 1
}
# system-specific logs may be also be configured here.
(二)dmseg命令
dmesg命令可以显示系统的启动信息及硬件错误信息,系统某个硬件有问题时,可使用该命令排障。
注意这个命令显示的日志与/var/log/dmseg日志关系不大。
(三)last命令与lastb命令
last命令与lastb命令用于查看系统的登陆用户,它通过调用系统日志/var/log/wtmp与/var/log/btmp来显示系统最近的用户登陆情况,在进行安全防范时要使用该命令。
>last
>lastb
日志/var/log/wtmp与/var/log/btmp是二进制文件,不能直接cat
与系统安全相关的日志还有secure日志(/var/log/secure),他记录了用户尝试登陆系统,或者暴力破解系统密码时的信息,帮助你进行下一步处理,比如用fail2ban来锁定攻击IP。
二、screen工具
screen是一个虚拟终端工具,一些程序的执行时间很长不能中途中断,而我们登陆服务器时是远程登陆的,为了防止系统意外中断时仍能持续运行一个程序我们就可以使用screen工具。注意即使我们断开
screen工具非系统自带,首先需要yum安装
工具选项
ctrl+A 再+D:新建一个screen
screen -S “自定义名字” :自定义终端名新建screen
screen -ls :列出系统中存在的screen
screen -r id号或者自定义名字:进入特定的screen
操作示例
1、新建一个screen并运行vnstat 1命令
screen
vmstat 1
ctrl+A 再+D
他就移到后台了
2、切换回到刚在的screen
screen -r 1960
screen -r test1
两个都可以,后一个是用screen -s test1生成的。
3、杀死一个已经detached的screen会话
screen -X -S (id号或者screen名字) quit
以上是关于[日志管理] 启动程序时,因报“log4j-slf4j-impl cannot be present with log4j-to-slf4j”错误而导致程序终止运行[转发]的主要内容,如果未能解决你的问题,请参考以下文章