Java 使用可执行 JAR 时指定 Log4j2 配置文件
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/28574905/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Specifying Log4j2 Configuration File When Using Executable JAR
提问by Steph
I am having trouble specifying the Log4j2 config file location when using an executable JAR file. 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 文件时,我无法指定 Log4j2 配置文件位置。如果我将所有 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. 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 (e.g. Log4j-config.xsd, Log4j-events.dtd, etc.).
所以我发现即使我正在构建的可执行 JAR 在其中log4j-core-2.1.jar
和文件的类路径中包含和log4j-api-2.1.jar
JAR MANIFEST
,也存在问题。我编写我的 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
如下所述,第一个命令将不起作用,因为MANIFEST
JAR 中指定的类路径会覆盖命令行中指定的任何类路径。
Thanks for your responses, they definitely helped me get on the right path toward figuring out my mistakes.
感谢您的回复,他们绝对帮助我走上了正确的道路,以找出我的错误。
采纳答案by rewolf
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. It will not listen to the -cp
or --classpath
arguments.
在 Java 文档中没有很好/明显地解释的事情是,如果您使用的是可执行 Jar,它将仅使用清单文件中指定的类路径。它不会听-cp
或--classpath
论点。
-Dlog4j.configurationFile=directory/file.xml
-Dlog4j.configurationFile=directory/file.xml
should definitely work though. I'm assuming you're running on Windows given your slash direction. Are you sure you are running it from the correct relative directory?
不过应该肯定有效。鉴于您的斜线方向,我假设您在 Windows 上运行。您确定是从正确的相对目录运行它吗?
Update
更新
I just tried it in Windows with no problems. I used the following manifest:
我只是在 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
The Log4j2 jars are located in a lib/
directory and the log4j2.xml
is in the conf/
directory. I executed the following command, and it found the config successfully.
Log4j2 jar 位于一个lib/
目录中,并且log4j2.xml
位于该conf/
目录中。我执行了以下命令,它成功找到了配置。
java -Dlog4j.configurationFile=conf\log4j2.xml -jar log4j2test1-1.0-SNAPSHOT.jar
回答by kervin
For others who may have this issue...
对于可能有此问题的其他人...
- Make sure your -Dlog4j.configurationFileoptions occur beforeyour '-jar' not after. Might seem obvious, but saw that mistake once.
- Try treating the file location as a url and see if that works. I.e. escape spaces with %20etc. Also use 'file://path', replace backslashes with forwardslashes.
- Windows paths can be written as file://c:/path/to/log4j2.xml
- 确保您的-Dlog4j.configurationFile选项出现在“-jar”之前而不是之后。可能看起来很明显,但曾经看到过这个错误。
- 尝试将文件位置视为 url,看看是否有效。即用%20等转义空格。也使用'file:// path',用正斜杠替换反斜杠。
- 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...
因此,如果您的程序文件夹中有一个 log4j2.xml 用于您的 exampleApp,C:\Program Files\ExampleApp
那么...
java.exe -Dlog4j.configurationFile=file://c:/program%20files/exampleapp/log4j2.xml -jar exampleApp.jar ...
...should work
...应该管用
回答by David Miller
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):
我有一个包,所以我需要指定我的“资源”文件夹的路径(在 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:
为了使这 2 个动态 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. 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.
在我的课程开始时声明“logger”(但在我的 2 个 System.setProperty 语句之前没有调用“getLogger”)使我能够在其他方法中引用“logger”。我不得不初始化它,所以我选择了“null”,但后来用“getLogger”语句更新它 - 鉴于此我不能使它成为“最终”(只能分配一次)但可以使它成为静态 -一个常量类变量。
nb the 2 log4j2 jars I included in the build path are:
请注意,我在构建路径中包含的 2 个 log4j2 jar 是:
log4j-api-2.6.2.jar
log4j-core-2.6.2.jar
log4j-api-2.6.2.jar
log4j-core-2.6.2.jar
回答by sujeet suryawanshi
I had this issue with version 2.8 of Log4j2. This was gone when the respective Log4j2 jars were replaced with version 2.6 of Log4j2.
我在 Log4j2 的 2.8 版中遇到了这个问题。当相应的 Log4j2 jar 被 Log4j2 的 2.6 版替换时,这种情况就消失了。