最近开发的SpringBoot项目上线了,运维那边反馈log.path_IS_UNDEFINED目录是什么,怎么在根目录上自动生成了,询问是否能配置。由于今年才转Java,所以运维的问题不知道怎么回答,立马查看项目配置以及百度一下是什么情况,该如何配置不让自动生成log.path_IS_UNDEFINED目录。

项目是将配置文件和第三方包打包到jar外面的,打包后的目录如下:

项目使用的LogBack日志组件,LogBack的配置直接参考其他项目配置的,application.yml里面的logback相关的配置如下:

# logback config
logging:
  config: classpath:logback-spring.xml

# config for logback file.
project:
  log:
    path: ./logs
    level: INFO

logback-spring.xml文件的部分配置如下,主要是将项目的project.log.path和project.log.level赋值给log.path和log.level,使项目可以配置日志存放的目录和记录哪些类型的日志。

    <!--use spring config kv. -->
    <springProperty scope="context" name="log.path" source="project.log.path" />
    <springProperty scope="context" name="log.level" source="project.log.level" />

    <!-- output info logger -->
    <appender name="INFO_FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
        <file>${log.path}/log_info.log</file>
        <encoder>
            <pattern>${fileLayoutPattern}</pattern>
            <charset>UTF-8</charset>
        </encoder>
        <!-- 日志记录器的滚动策略,按日期,按大小记录 -->
        <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
            <fileNamePattern>${log.path}/info/log-info-%d{yyyy-MM-dd}.%i.log</fileNamePattern>
            <timeBasedFileNamingAndTriggeringPolicy class="ch.qos.logback.core.rolling.SizeAndTimeBasedFNATP">
                <maxFileSize>${log.file.size}</maxFileSize>
            </timeBasedFileNamingAndTriggeringPolicy>
            <maxHistory>${log.history.days}</maxHistory>
        </rollingPolicy>
        <filter class="ch.qos.logback.classic.filter.LevelFilter">
            <level>info</level>
            <onMatch>ACCEPT</onMatch>
            <onMismatch>DENY</onMismatch>
        </filter>
    </appender>

通过查看项目的日志配置,发现项目是拥有配置日志存放目录的功能的。本地和测试环境测试后,发现会在执行的bash文件同目录下生成logs和log.path_IS_UNDEFINED目录,logs目录是application.yml配置的目录,但是log.path_IS_UNDEFINED目录为什么会自动生成呢?

通过搜索,发现是因为LogBack比SpringBoot先初始化,LogBack初始化时会去查找log.path变量的值,但是上面的配置已经决定了该log.path的值由Spring来解析,所以先行初始化的logback找不到该变量的值,导致出现上面log.path_IS_UNDEFINED描述的情况。

参考https://www.jianshu.com/p/e326af51bee5增加defaultValue,直接修改logback-spring.xml配置,增加defaultValue重启服务,发现还是会生成log.path_IS_UNDEFINED目录。

<springProperty scope="context" name="log.path" source="project.log.path" defaultValue="./logs"/>

1.由于项目是将配置文件打包到jar外面的,直接修改logback-spring.xml是不会起作用的,可以运行jar包的时候将-Dlogging.config="E:\logback-spring.xml"设置为系统属性实现读取jar外部的logback-spring.xml配置文件。这样会导致我们在application.yml中配置了日志目录,还要在logback-spring.xml中再次为defaultVaule配置一次日志目录,重复配置了,不是理想的方案。

2.或者在项目中修改logback-spring.xml配置,然后重新打包。但是这样就会导致运维那边无法配置defaultValue,会在执行bash文件的同目录下生成logs目录,这种方式无法满足需求。

3.通过方案1中的思考,直接将project.log.level变量设置在系统属性层面,运行jar包的时候增加-Dproject.log.level="./logs"配置,现实日志目录的配置,解决掉自动生成log.path_IS_UNDEFINED目录的问题。该中方法的配置为优先级高于applicatioin.yml的配置,所以application.yml中的日志目录配置将无效。配置示例如下:

# 服务所在目录 请使用绝对路径
APP_HOME=/usr/local/webroot/project
# JVM内存参数
JAVA_OPTS="-Xmx5g -Xms3g -Xmn1g -Xss1m"
# 服务日志目录
APP_LOG_HOME=${APP_HOME}/logs
# 服务配置文件目录
CONF_FILE=${APP_HOME}/config/
# 服务启动的jar包
PROJECT_NAME=${APP_HOME}/demo-1.0-SNAPSHOT.jar

nohup java ${JAVA_OPTS} -Djava.ext.dirs=${APP_HOME}/lib::$JAVA_HOME/jre/lib/ext -Dspring.config.location=${CONF_FILE} -Dproject.log.path=${APP_LOG_HOME} -jar ${PROJECT_NAME} >/dev/null 2>&1 &

通过搜索和测试使用#3的方案解决了生成环境logback自动生成log.path_IS_UNDEFINED目录的问题,这是目前博主解决该问题的方案。对于logback并没有深入的研究,如果有更好的方案欢迎提出。同时也希望本片博客可以给其他小伙伴提供帮助,如果有描述错误的地方欢迎指正。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐