使用可执行JAR时指定Log4j2配置文件

时间:2015-02-18 02:21:19

标签: java logging executable-jar log4j2

使用可执行JAR文件时,我无法指定Log4j2配置文件位置。如果我将所有JAR分开,它可以正常工作,但是当我尝试将它们组合成一个可执行的JAR文件时,由于某种原因,log4j2.xml文件没有从命令行中获取。

我已尝试过这两种指定位置的方法:

java -Djava.libary.path=..\bin -cp ..\config -jar MyApplication.jar

java -Djava.libary.path=..\bin -Dlog4j.configurationFile=..\config\log4j2.xml -jar MyApplication.jar

这些都没有奏效。我还尝试将包含配置文件的目录添加到JAR的清单文件中的类路径中:

Manifest-Version: 1.0
Ant-Version: Apache Ant 1.9.2
Created-By: 1.7.0_21-b11 (Oracle Corporation)
Main-Class: com.abc.MyApplication
Class-Path: ../config/

我也没有成功使用这种方法。我可能做错了什么想法?

提前感谢您的帮助!


修改

啊,我相信我误解了这个问题。最初,这是我在命令行输出中看到的错误:

ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

但是在我改变事物的某个时刻,错误消息发生了变化而我没有意识到这一点:

ERROR StatusLogger Log4j2 could not find a logging implementation. Please add log4j-core to the classpath. Using SimpleLogger to log to the console...

所以我想到的是,即使我正在构建的可执行JAR包含log4j-core-2.1.jarlog4j-api-2.1.jar JAR内部以及MANIFEST文件的类路径,有一个问题。我编写我的ant文件以将库组合到我正在创建的单个JAR中的方式是成功复制目录和类文件,但由于某些原因没有复制其他类型,这显然也是必要的(例如Log4j-config .xsd,Log4j-events.dtd等。)。

为了解决这个问题,我改变了我在Ant构建文件中合并JAR的方式:

<jar destfile="${dist}/${jarName}" basedir="${classes}" 
    excludes=".svn">

    <!-- Merge this JAR with all the JARs in the lib directory, so that
    we are only creating one distribution JAR that includes all the
    libraries that you need. -->
    <fileset dir="${classes}" includes="**/*.class" />
    <zipgroupfileset dir="${lib}" includes="**/*.jar" />

    <!-- Specify the manifest file of the JAR -->
    <manifest>
        <attribute name="Main-Class" value="com.abc.MyApplication"/>
        <attribute name="Class-Path" value=". ${manifest.classpath}"/>
    </manifest>
</jar>

这解决了问题并将所有文件从JAR复制到我新创建的JAR中。

解决此问题后,我上面发布的第二个命令用于指定配置文件的位置。 (如下面@rewolf所述,第一个命令不起作用,因为JAR的MANIFEST中指定的类路径会覆盖命令行上指定的任何类路径。

感谢您的回复,他们肯定帮助我找到了解决错误的正确道路。

4 个答案:

答案 0 :(得分:15)

Java文档中没有很好解释的东西是,如果你使用的是可执行的Jar,它只会使用Manifest文件中指定的Class-Path。它不会收听-cp--classpath个参数。

-Dlog4j.configurationFile=directory/file.xml

绝对应该工作。考虑到你的斜线方向,我假设你在Windows上运行。你确定从正确的相对目录运行它吗?

<强>更新

我刚在Windows中尝试过没有问题。我使用了以下清单:

Manifest-Version: 1.0
Built-By: andrew.flower
Build-Jdk: 1.7.0_67
Class-Path: lib/log4j-api-2.1.jar lib/log4j-core-2.1.jar
Created-By: Apache Maven 3.2.3
Main-Class: com.andrew_flower.test.Log4jTest
Archiver-Version: Plexus Archiver

Log4j2 jar位于lib/目录中,log4j2.xml位于conf/目录中。我执行了以下命令,它成功找到了配置。

java -Dlog4j.configurationFile=conf\log4j2.xml -jar log4j2test1-1.0-SNAPSHOT.jar

答案 1 :(得分:6)

我解决了在Eclipse中创建的可运行Jar中指定log4j2配置位置的问题,方法是将其包含在我的java代码中:

System.setProperty("log4j.configurationFile", "resources/log4j2.xml");

我有一个包,所以我需要指定我的&#34;资源&#34;文件夹(在我的&#34; src&#34; Eclipse中的文件夹):

System.setProperty("log4j.configurationFile", "com/company/app/resources/log4j2.xml");

注意我没有包含&#34; src&#34;在我的道路上,我认为它是&#34; bin&#34;所需的文件夹:即在我的情况下&#34; com / company / app / resources / log4j2.xml&#34;

我的配置文件如下所示:

<?xml version="1.0" encoding="UTF-8"?>
<Configuration> 

<appenders>

<Console name="Console" target="SYSTEM_OUT">
  <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} %-5level - %msg%n"/>  
</Console>

<RollingFile 
        name="RollingFile" 
        fileName="${sys:logFilename}"
        filePattern="${sys:logFilename}-%d{yyyy-MM-dd}-%i.log"> 
  <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss.SSS} [%t] %-5level - %msg%n"/>      
  <Policies>
    <SizeBasedTriggeringPolicy size="1 MB"/>
  </Policies>  
  <DefaultRolloverStrategy max="10"/> 
</RollingFile>

</appenders> 


<loggers>     
 <root level="all">
  <appender-ref ref="Console"/>      
  <appender-ref ref="RollingFile"/> 
 </root>    
</loggers>

另请注意,我动态分配滚动日志文件路径+名称&#34; $ {sys:logFilename}&#34;将其包含在我的java代码中:

System.setProperty("logFilename", "logs/myApp.log");

为了使这两个动态System.setProperty分配工作,他们需要在&#34; getLogger&#34;之前执行。声明,所以我的java代码看起来像:

import org.apache.logging.log4j.LogManager;
import org.apache.logging.log4j.Logger;

public class MyTestLoggingClass {

 public static Logger logger = null;

 ...................
 setUpLogging();
 ...............

 public static void setUpLogging() {
    System.setProperty("log4j.configurationFile",  "com/company/app/resources/log4j2.xml");
    System.setProperty("logFilename", "logs/myApp.log");

    logger = LogManager.getLogger(Logger.class.getName());  
 }

}

拥有&#34;记录器&#34;在我的课程开始时声明(但是没有调用&#34; getLogger&#34;在我的2个System.setProperty语句之前)使我能够引用&#34; logger&#34;在其他方法。我不得不对它进行初始化,因此我选择了&#34; null&#34;但后来用&#34; getLogger&#34;更新它。陈述 - 鉴于此,我无法做到#34; final&#34; (只能分配一次)但可以使它成为静态 - 一个常量类变量。

我在构建路径中包含的2个log4j2罐子是:

  1. 的log4j-API-2.6.2.jar

  2. log4j的核 - 2.6.2.jar

答案 2 :(得分:4)

对于可能遇到此问题的其他人......

  1. 确保您的 -Dlog4j.configurationFile 选项出现 之前的<-strong>&#39; -jar&#39;不是之后。可能看起来很明显,但是曾经看过那个错误。
  2. 尝试将文件位置视为网址,看看是否有效。即使用%20 等转义空格。也可以使用&#39; file:// path &#39;,用反斜杠替换反斜杠。
  3. Windows路径可以写为 file:// c:/path/to/log4j2.xml
  4. 因此,如果C:\Program Files\ExampleApp中的exampleApp的程序文件夹中有log4j2.xml,那么......

    java.exe -Dlog4j.configurationFile=file://c:/program%20files/exampleapp/log4j2.xml -jar exampleApp.jar ... 
    

    ......应该有效

答案 3 :(得分:0)

我在Log4j2的2.8版本中遇到了这个问题。 当各个Log4j2罐用Log4j2的2.6版替换时,这种情况就消失了。