【问题标题】:Read environment variables from logback configuration file从 logback 配置文件中读取环境变量
【发布时间】:2010-12-30 20:41:37
【问题描述】:

我有这个 logback.xml 文件:

<configuration debug="true" scan="true" scanPeriod="60 seconds">

  <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level %logger{36} - %msg%n</Pattern>
    </layout>
  </appender>

  <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
    <File>${MY_HOME}/logs/mylog.log</File>

    <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
      <FileNamePattern>logs/my.%d{yyyy-MM-dd}.log</FileNamePattern>
      <MaxHistory>30</MaxHistory>
    </rollingPolicy>

    <layout class="ch.qos.logback.classic.PatternLayout">
      <Pattern>%d{HH:mm:ss.SSS} [%thread] %-5level - %msg%n</Pattern>
    </layout>

  </appender> 

  <root level="TRACE">
    <appender-ref ref="FILE"/>
  </root>

</configuration>

${MY_HOME} 是一个已定义的系统变量(Linux 上的echo $MY_HOME 显示正确的路径)。

问题是logback似乎没有正确读取它,它将日志存储在MY_HOME_IS_UNDEFINED/logs/my.log

我做错了什么?非常感谢!

编辑:我犯了一个错误,将 OSC_HOME 放在我真正指的是 MY_HOME 的位置。对此感到抱歉

【问题讨论】:

    标签: java logging environment-variables logback


    【解决方案1】:

    如果您使用的是 Eclipse,则必须重新启动它以获取环境变量,但您不能使用:File -> Restart

    实际上,您必须将其完全关闭,然后再重新启动

    【讨论】:

      【解决方案2】:

      还有另一种从配置文件中读取环境变量的方法。您可以使用上下文侦听器将自定义变量放入 logback 上下文。

      logback.xml

      <?xml version="1.0" encoding="UTF-8"?>
      <configuration debug="true" scan="true" scanPeriod="30 seconds">
      
          <!-- THIS IS OUR CUSTOM CONTEXT LISTENER -->
          <contextListener class="com.myapp.logging.listener.LoggerStartupListener"/>
      
          <appender name="STDOUT" class="ch.qos.logback.core.ConsoleAppender">
              <encoder>
                  <pattern>[%-5level] %d{HH:mm:ss.SSS} [%.6thread] %logger - %msg%n</pattern>
                  <charset>UTF-8</charset>
              </encoder>
          </appender>
      
          <appender name="FILEOUT" class="ch.qos.logback.core.rolling.RollingFileAppender">
              <file>${MY_HOME}/${LOG_FILE}.log</file>
              <append>true</append>
              <!-- Support multiple-JVM writing to the same log file -->
              <prudent>true</prudent>
              <rollingPolicy class="ch.qos.logback.core.rolling.TimeBasedRollingPolicy">
                  <!-- Daily rollover -->
                  <fileNamePattern>${MY_HOME}/${LOG_FILE}.%d{yyyy-MM-dd}.log</fileNamePattern>
                  <!-- Keep 7 days' worth of history -->
                  <maxHistory>7</maxHistory>
              </rollingPolicy>
              <encoder>
                  <pattern>[%-5level] %d{HH:mm:ss.SSS} [%.6thread] %logger - %msg%n</pattern>
                  <charset>UTF-8</charset>
              </encoder>
          </appender>
      
          <root level="INFO">
              <appender-ref ref="STDOUT"/>
              <appender-ref ref="FILEOUT"/>
          </root>
      </configuration>
      

      LoggerStartupListener.java

      package com.myapp.logging.listener;
      
      import ch.qos.logback.classic.Level;
      import ch.qos.logback.classic.Logger;
      import ch.qos.logback.classic.LoggerContext;
      import ch.qos.logback.classic.spi.LoggerContextListener;
      import ch.qos.logback.core.Context;
      import ch.qos.logback.core.spi.ContextAwareBase;
      import ch.qos.logback.core.spi.LifeCycle;
      
      public class LoggerStartupListener extends ContextAwareBase implements LoggerContextListener, LifeCycle {
      
          private static final String DEFAULT_LOG_FILE = "MYAPP";
      
          private boolean started = false;
      
          @Override
          public void start() {
              if (started) return;
      
              String userHome = System.getProperty("user.home"); 
      
              String logFile = System.getProperty("log.file"); // log.file is our custom jvm parameter to change log file name dynamicly if needed
      
              logFile = (logFile != null && logFile.length() > 0) ? logFile : DEFAULT_LOG_FILE;
      
              Context context = getContext();
      
              context.putProperty("MY_HOME", userHome);
              context.putProperty("LOG_FILE", logFile);
      
              started = true;
          }
      
          @Override
          public void stop() {
          }
      
          @Override
          public boolean isStarted() {
              return started;
          }
      
          @Override
          public boolean isResetResistant() {
              return true;
          }
      
          @Override
          public void onStart(LoggerContext context) {
          }
      
          @Override
          public void onReset(LoggerContext context) {
          }
      
          @Override
          public void onStop(LoggerContext context) {
          }
      
          @Override
          public void onLevelChange(Logger logger, Level level) {
          }
      }
      

      【讨论】:

      • 需要包含 aws ec2 实例 ID 的日志。这是我必须采取的方法。
      【解决方案3】:

      与其他人所说的相反,logback documentation explicitly states “在替换期间,首先在本地范围内查找属性,然后在上下文范围内查找,然后在系统属性范围内查找,然后 在操作系统环境中第四个也是最后一个”。所以如果在环境中定义了属性,logback会找到它。

      我在 Eclipse 中运行我的项目时遇到了同样的问题。如果这是您遇到的问题,可以通过转到运行配置 -> 环境并将MY_HOME 添加到环境变量来解决。

      不确定为什么默认情况下它不加载本机环境。甚至还有一个名为“将环境附加到本机环境”的选项,这似乎对我没有任何影响。

      【讨论】:

      • 环境变量对我有用,但我必须重新启动 Eclipse 才能获取它们。查看我对这个问题的回答
      • 这对于 IntelliJ IDEA 是一样的。应用程序的完全重启将获取环境变量。
      【解决方案4】:

      你可以在logback.xml中使用tag来声明变量,而不是使用环境变量。

      【讨论】:

        【解决方案5】:

        事情实际上按设计工作:在进行变量替换时,logback 根本不读取环境变量。引用documentation

        替代变量的值可以在配置文件本身、外部属性文件或系统属性中定义。

        所以,要么使用上述解决方案之一,要么获取OSC_HOME_IS_UNDEFINED :)

        【讨论】:

        • Logback 确实会读取操作系统环境变量。在Scopes 下,它提到了“OS 环境”,这是指向 Oracle 环境变量文档的链接
        • 以上引用确实暗示不支持操作系统环境变量。但是,我在文档中找不到上述引用。当前的文档明确提到了操作系统环境变量。
        【解决方案6】:

        您的意思可能是MY_HOME。在您的配置文件中有OSC_HOME 的引用。详见Variable substitutionLogback规则。

        您可以将环境变量作为 Java 系统属性传递,然后 Logback 将执行变量替换。您可以在命令行中将此作为 JVM 选项传递。例如:

        java -DMY_HOME=${MY_HOME} -cp ... MainClass
        

        或者您可以在配置文件中定义 MY_HOME。

        <configuration debug="true" scan="true" scanPeriod="60 seconds">
          <property name="MY_HOME" value="/home/my" />
          <appender name="FILE" class="ch.qos.logback.core.rolling.RollingFileAppender">
            <File>${MY_HOME}/logs/mylog.log</File>
          </appender> 
        </configuration>
        

        【讨论】:

        • 来自您回答中的链接:“在替换期间,首先在本地范围内查找属性,然后在上下文范围内查找,然后在系统属性范围内查找,然后在 操作系统环境第四个也是最后一个。”所以应该是看 os 环境变量吧?
        • @TimPote 是的,它会查看操作系统环境变量
        猜你喜欢
        • 2017-03-06
        • 2019-08-27
        • 1970-01-01
        • 1970-01-01
        • 2019-12-03
        • 1970-01-01
        • 2015-11-10
        • 2020-09-02
        • 1970-01-01
        相关资源
        最近更新 更多