简体   繁体   English

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

[英]Specifying Log4j2 Configuration File When Using Executable JAR

I am having trouble specifying the Log4j2 config file location when using an executable JAR file. 使用可执行JAR文件时,我无法指定Log4j2配置文件位置。 It works fine if I separate all the JARs, but when I try to combine them into one executable JAR file, for some reason the log4j2.xml file isn't picked up from the command line. 如果我将所有JAR分开,它可以正常工作,但是当我尝试将它们组合成一个可执行的JAR文件时,由于某种原因,没有log4j2.xml文件。

I've tried these two methods of specifying the location: 我已经尝试了这两种指定位置的方法:

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

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

Neither of those are working. 这些都没有奏效。 I've also tried adding the directory containing the config file to the classpath in the JAR's manifest file: 我还尝试将包含配置文件的目录添加到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/

I haven't had success with this method either. 我也没有成功使用这种方法。 Any ideas what I might be doing wrong? 我有什么想法可能做错了吗?

Thanks in advance for any help! 在此先感谢您的帮助!


EDIT 编辑

Ah, I believe I mistook the problem. 啊,我相信我误解了这个问题。 Originally, this was the error I was seeing in the command line output: 最初,这是我在命令行输出中看到的错误:

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

But at some point while I was changing things, the error message changed without my realizing it to this: 但是在我改变事物的某个时刻,错误消息发生了变化而我没有意识到这一点:

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

So what I figured out was that even though the executable JAR I was building was including the log4j-core-2.1.jar and log4j-api-2.1.jar JARs inside of it and in the MANIFEST file's classpath, there was a problem. 所以我想到的是,即使我正在构建的可执行JAR包含其中的log4j-core-2.1.jarlog4j-api-2.1.jar JAR以及MANIFEST文件的类路径,也存在问题。 The way I wrote my ant file to combine the libraries into the single JAR I was creating was successfully copying over the directories and class files, but was not copying over the other types for some reason, which are also obviously necessary (eg Log4j-config.xsd, Log4j-events.dtd, etc.). 我编写我的ant文件以将库组合到我正在创建的单个JAR中的方式是成功复制目录和类文件,但由于某些原因没有复制其他类型,这显然也是必要的(例如Log4j-config .xsd,Log4j-events.dtd等)。

To fix this, I changed the way I was merging the JARs in my Ant build file to this: 为了解决这个问题,我改变了将我的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>

And that fixed the issue and copied over all files from the JARs into my newly created JAR. 这解决了问题并将所有文件从JAR复制到我新创建的JAR中。

Once this issue was resolved, the second of the commands I posted above worked for specifying the location of the configuration file. 解决此问题后,我上面发布的第二个命令用于指定配置文件的位置。 (As noted by @rewolf below, the first command won't work because the classpath specified in the MANIFEST of the JAR overrides any classpath specified on the command line. (如下面的@rewolf所述,第一个命令不起作用,因为JAR的MANIFEST中指定的类路径会覆盖命令行上指定的任何类路径。

Thanks for your responses, they definitely helped me get on the right path toward figuring out my mistakes. 感谢您的回复,他们肯定帮助我找到了解决错误的正确道路。

Something that isn't explained very well/obviously in the Java documentation is that if you're using an executable Jar, it will only use the Class-Path as specified in the Manifest file. Java文档中没有很好解释的东西是,如果你使用的是可执行的Jar,它只会使用Manifest文件中指定的Class-Path。 It will not listen to the -cp or --classpath arguments. 它不会侦听-cp--classpath参数。

-Dlog4j.configurationFile=directory/file.xml

should definitely work though. 绝对应该工作。 I'm assuming you're running on Windows given your slash direction. 考虑到你的斜线方向,我假设你在Windows上运行。 Are you sure you are running it from the correct relative directory? 您确定从正确的相对目录运行它吗?

Update 更新

I just tried it in Windows with no problems. 我刚刚在Windows中尝试过没有问题。 I used the following manifest: 我使用了以下清单:

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

The Log4j2 jars are located in a lib/ directory and the log4j2.xml is in the conf/ directory. Log4j2 jar位于lib/目录中, log4j2.xml位于conf/目录中。 I executed the following command, and it found the config successfully. 我执行了以下命令,它成功找到了配置。

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

I solved the problem of specifying the location of log4j2 configuration in a runnable Jar that I created from Eclipse by including this in my java code: 我解决了在我从Eclipse创建的可运行Jar中指定log4j2配置位置的问题,方法是将其包含在我的java代码中:

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

I have a package and so I needed to specify the path to my "resources" folder (in my "src" folder in Eclipse): 我有一个包,所以我需要指定我的“resources”文件夹的路径(在Eclipse的“src”文件夹中):

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

Notice I didn't include "src" in my path and I think it's the path in the "bin" folder that's required: ie in my case "com/company/app/resources/log4j2.xml" 注意我的路径中没有包含“src”,我认为这是“bin”文件夹中所需的路径:即在我的情况下“com / company / app / resources / log4j2.xml”

My configuration file looks like this: 我的配置文件如下所示:

<?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>

Also notice I dynamically assign the rolling log file path + name "${sys:logFilename}" by including this in my java code: 另请注意,我通过将其包含在我的java代码中来动态分配滚动日志文件路径+名称“$ {sys:logFilename}”:

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

In order to get these 2 dynamic System.setProperty assignments to work they need to execute before the "getLogger" statement and so my java code looks like: 为了使这两个动态System.setProperty赋值工作,他们需要在“getLogger”语句之前执行,所以我的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());  
 }

} }

Having "logger" declared at the start of my class (but without invoking "getLogger" before my 2 System.setProperty statements) enables me to reference "logger" in other methods. 在我的类的开头声明了“logger”(但是在我的2个System.setProperty语句之前没有调用“getLogger”)使我能够在其他方法中引用“logger”。 I am obliged to initialise it though and so I chose "null" but then later update it with the "getLogger" statement - given this I can't make it "final" (can only assign it once) but can make it static - a constant class variable. 我不得不初始化它,因此我选择了“null”但后来用“getLogger”语句更新它 - 鉴于此我不能使它“最终”(只能分配一次)但可以使它静态 - 一个常量类变量。

nb the 2 log4j2 jars I included in the build path are: 我在构建路径中包含的2个log4j2罐子是:

  1. log4j-api-2.6.2.jar log4j的-API-2.6.2.jar

  2. log4j-core-2.6.2.jar log4j的核心 - 2.6.2.jar

For others who may have this issue... 对于可能有这个问题的其他人......

  1. Make sure your -Dlog4j.configurationFile options occur before your '-jar' not after. 确保您的-Dlog4j.configurationFile选项 '-jar'之后发生。 Might seem obvious, but saw that mistake once. 可能看起来很明显,但是曾经看过那个错误。
  2. Try treating the file location as a url and see if that works. 尝试将文件位置视为网址,看看是否有效。 Ie escape spaces with %20 etc. Also use 'file:// path ', replace backslashes with forwardslashes. 即使用%20等转义空格。也可以使用'file:// path ',用反斜杠替换反斜杠。
  3. Windows paths can be written as file://c:/path/to/log4j2.xml Windows路径可以写为file:// c:/path/to/log4j2.xml

Hence if you have a log4j2.xml in your program folder for your exampleApp in C:\\Program Files\\ExampleApp then... 因此,如果在C:\\Program Files\\ExampleApp的exampleApp的程序文件夹中有log4j2.xml,那么......

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

...should work ...应该管用

I had this issue with version 2.8 of Log4j2. 我在Log4j2的2.8版本中遇到了这个问题。 This was gone when the respective Log4j2 jars were replaced with version 2.6 of Log4j2. 当各个Log4j2 jar用Log4j2的2.6版替换时,这种情况就消失了。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM