web-dev-qa-db-ja.com

実行可能JARを使用する場合のLog4j2構成ファイルの指定

実行可能なJARファイルを使用するときに、Log4j2構成ファイルの場所を指定するのに問題があります。すべてのJARを分離すると問題なく動作しますが、何らかの理由でそれらを1つの実行可能JARファイルに結合しようとすると、log4j2.xmlファイルがコマンドラインから取得されません。

場所を指定するこれらの2つの方法を試しました:

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.jarおよびlog4j-api-2.1.jar JARが内部にあり、MANIFESTファイルのクラスパスに問題があります。ライブラリを組み合わせて作成中の単一のJARにするためにantファイルを作成した方法は、ディレクトリとクラスファイルを正常にコピーしていましたが、何らかの理由で他のタイプをコピーしていませんでした。これも明らかに必要です(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にコピーされました。

この問題が解決されると、上記で投稿した2番目のコマンドは、構成ファイルの場所を指定するために機能しました。 (@rewolf以下では、JARのMANIFESTで指定されたクラスパスがコマンドラインで指定されたクラスパスをオーバーライドするため、最初のコマンドは機能しません。

あなたの回答をありがとう、間違いは私が間違いを理解するための正しい道に進むのを確実に助けました。

12
Steph

Javaのドキュメントで十分に/明らかに説明されていないものは、実行可能なJarを使用している場合、マニフェストファイルで指定されている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.xmlconf/ディレクトリにあります。次のコマンドを実行すると、設定が正常に検出されました。

Java -Dlog4j.configurationFile=conf\log4j2.xml -jar log4j2test1-1.0-SNAPSHOT.jar
18
rewolf

これをJavaコードに含めることで、Eclipseから作成した実行可能なJARでlog4j2構成の場所を指定する問題を解決しました。

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

私はパッケージを持っているので、「Eclipse」の「src」フォルダー内の「resources」フォルダーへのパスを指定する必要がありました。

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

パスに「src」を含めておらず、必要なのは「bin」フォルダー内のパスだと思います。つまり、私の場合は「com/company/app/resources/log4j2.xml」です。

私の設定ファイルは次のようになります:

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

また、これをJavaコードに含めることで、ローリングログファイルのパス+名前 "$ {sys:logFilename}"を動的に割り当てています。

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

これらの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());  
 }

}

クラスの開始時に「ロガー」が宣言されている(ただし、2つのSystem.setPropertyステートメントの前に「getLogger」を呼び出さない)と、他のメソッドで「ロガー」を参照できます。私はそれを初期化する義務があるので、「null」を選択しましたが、後で「getLogger」ステートメントで更新します-これを考えると、「最終」にすることはできません(1回だけ割り当てることができます)が、静的にすることができます-定数クラス変数。

ビルドパスに含めた2つのlog4j2 jarは次のとおりです。

  1. log4j-api-2.6.2.jar

  2. log4j-core-2.6.2.jar

6
David Miller

この問題があるかもしれない他の人のために...

  1. -Dlog4j.configurationFileオプションが発生することを確認してくださいbefore '-jar'が後ではありません。当たり前のように思えるかもしれませんが、その間違いを一度見ました。
  2. ファイルの場所をURLとして扱い、それが機能するかどうかを確認してください。つまり%20などでスペースをエスケープします。'file://path '、バックスラッシュをフォワードスラッシュに置き換えます。
  3. Windowsパスはfile:// c:/path/to/log4j2.xmlとして記述できます

したがって、C:\Program Files\ExampleAppのexampleAppのプログラムフォルダーにlog4j2.xmlがある場合は、...

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

...うまくいくはず

4
kervin

Log4j2のバージョン2.8でこの問題が発生しました。これは、それぞれのLog4j2 jarがバージョン2.6のLog4j2に置き換えられたときになくなりました。

0