问题

    这两天遇到一个很神奇的问题,手上的一个项目日志打印异常,我在resources目录下放了logback.xml但是在linux上却不生效,如果本地直接用IDEA启动时生效的,然后网上查出一堆关于logback.xml该怎么配之类的,该放在那里答案。如果你是第一次配这种东西,可能是不小心改错了,但这明显不是我要的答案。

分析

    项目结构是采用的springboot结构,但是由于项目里是调度程序,在linux通过crontab来进行调度,所以部署到linux时,打成了jar包,通过shell执行java -jar xxx.java来启动程序的。
    检查确认完不是各种粗心造成的问题之后,把眼观聚焦到了logback本地有效,但部署到linux上却不生效了这一点上,不同环境上效果不同,是不是由于编译部署方式不同造成的,所以把目光转向了编译部署工具(maven)上。看了pom.xml中的打包编译配置:

                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-dependency-plugin</artifactId>

                <groupId>org.apache.maven.plugins</groupId>
                <artifactId>maven-jar-plugin</artifactId>

使用的是这两个插件,是将项目打成了jar包,同时把当前项目的其他依赖jar包也都复制到项目本身的jar所在的目录,也就是所有jar包都在同一目录下。而本地通过IDEA启动时,都是按照springboot的层次结构编译执行的,而springboot这种层次结构里,依赖jar包的层次是比项目本身的入口更低一层。而本地有效,maven编译后在linux上无效了,是不是因为其他jar包里还有一个logback.xml文件,当所有jar包都在同一层次的时候,应用去读了别的jar包里的logback.xml呢?
    为了验证这一点,我将linux上那个目录下的jar包全部解压出来,然后一搜索,果然在另外一个jar包还有一个logback.xml。其实想发现这个问题,还有另外一个方法,就是看日志,由于logback.xml不生效,日志全部都打印到了控制台上,我们可以通过./xxx.sh > test.log,将控台上的日志打印进文件中,然后打开文件,最上面我们就可以看到logback的加载日志:

10:56:46,765 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback.groovy]
10:56:46,766 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Could NOT find resource [logback-test.xml]
10:56:46,766 |-INFO in ch.qos.logback.classic.LoggerContext[default] - Found resource [logback.xml] at [jar:file:/app/uttf/lib/sadk-kit-1.0.0.jar!/logback.xml]
10:56:46,767 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs multiple times on the classpath.
10:56:46,767 |-WARN in ch.qos.logback.classic.LoggerContext[default] - Resource [logback.xml] occurs at [jar:file:/app/uttf/lib/sadk-kit-1.0.0.jar!/logback.xml]

就可以很清晰的看到logback到底加载了哪一个配置文件了。

尝试解决方案

    知道了产生原因,但是解决起来依旧一波三折,一开始以为可以通过在springboot的配置文件中来指定路径,网上也搜到了答案,但是换了好几个参数,试验下来并没有效果,后来发现,logback的加载是早于spring的,比如我们看日志的时候,最上级就是logback,而spring还要往后一些,所以你在spring里配logback的配置文件路径毫无意义。

    后来换了个思路,能不能通过maven,在打包的时候把另外一个logback.xml文件给踢出去,网上也搜到了一些资料,如下:

<plugin>
    <groupId>org.apache.maven.plugins</groupId>
    <artifactId>maven-jar-plugin</artifactId>
    <configuration>
        <excludes>
            <exclude>**/logback.xml</exclude>
        </excludes>

        <!-- 下面还有一些其他无关的编译的配置,就不显示了 -->
    </configuration>
</plugin>

通过这样的方式剔除,事实证明也是无效的,反而把我自己的logback.xml个剔除了,所以这种剔除应该是剔除自己当前项目中的配置文件的,对于依赖jar包中的配置文件是无能为力的。

正确解决方案

    既然无法删除,还是只能靠配置正确的路径来解决,最后找到了通过jvm增加logback.configurationFile配置来解决,一种通过在启动参数中加入-Dlogback.configurationFile=file path/logback.xml,另一种是通过在代码中增加System.setProperty(key,value)来解决。后来进行了尝试,还是没有效果,后来查日志发现了问题,里面有一串警告大概意思是,spring项目中使用logging.config替代logback.configurationFile,然后尝试了一下,得以解决。这里是通过代码实现的:

    static {
        System.setProperty("logging.config","jar:file:***/logback.xml");
    }

***表示路径,这段静态块需要写在最前面,至少在spring前面,在尝试解决中有说到过,logback加载的很早,拟配置晚了就没意义了,用这个配置有一个难点是路径到底填什么,如果大家要使用的话,各自的项目需要自己斟酌一下的。

Logo

更多推荐