运行fatjar时加载log4j2失败

5ktev3wc  于 2021-06-04  发布在  Flume
关注(0)|答案(5)|浏览(730)

我在一个利用log4j2日志的项目上工作。在intellij中进行开发时,所有的工作都很好,日志记录也按预期完成。log4j2.xml通过java属性链接,java属性在启动时通过intellij设置传递给jvm。但一旦我尝试运行一个独立的gradle构建的fat jar,我就会遇到以下问题:

java -Dlog4j.debug=true -Dlog4j.configurationFile=/home/aaa/log4j2.xml -jar /home/aaa/myjar-SNAPSHOT.jar

例外情况:

ERROR StatusLogger Unrecognized format specifier [d]
ERROR StatusLogger Unrecognized conversion specifier [d] starting at position 16 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [thread]
ERROR StatusLogger Unrecognized conversion specifier [thread] starting at position 25 in conversion pattern.
...
ERROR StatusLogger No log4j2 configuration file found. Using default configuration: logging only errors to the console.

我甚至不知道这些[线程]是从哪里来的,因为即使在log4j2中使用最简单的基本配置,我也会遇到同样的错误:

<?xml version="1.0" encoding="UTF-8" ?><Configuration status="WARN" monitorInterval="86400">
<Appenders>
    <Console name="console-log" target="SYSTEM_OUT">
        <PatternLayout
                pattern="%-5p %d{yyyy-MM-dd HH:mm:ss.SSS} ${hostName} %c{1} %msg %throwable{7}%n"/>
    </Console>
</Appenders>
<Loggers>
    <Root level="info" additivity="false">
        <AppenderRef ref="console-log"/>
    </Root>
</Loggers>

欢迎有任何想法。谢谢。

mfpqipee

mfpqipee1#

参加这个聚会有点晚了,但我想我应该补充一下我的情况,以防对任何人都有帮助。
我从大型项目的类和jar的子集中构建自己的胖jar。基本类运行,但我得到了所有“无法识别的格式说明符”和所有。大多数答案都涉及mvn shade或其他类似的问题,所以这对我没有帮助。但是仔细观察,我发现log4j-web.jar还包含log4jplugins.dat文件,从而导致了这些问题。从构建中移除,一切都很好。
(我认为我的构建脚本非常复杂,包括按项目名称列出的所有jar,例如“log4j”的所有jar。)

ws51t4hk

ws51t4hk2#

问题描述如下:https://issues.apache.org/jira/browse/log4j2-673
不幸的是,目前似乎只有maven shade插件的解决方案:https://github.com/edwgiz/maven-shaded-log4j-transformer

<plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>2.4.3</version>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <finalName>${project.artifactId}${appSuffix}</finalName>
                        <transformers>
...
                            <transformer
                                    implementation="com.github.edwgiz.mavenShadePlugin.log4j2CacheTransformer.PluginsCacheFileTransformer">
                            </transformer>
                        </transformers>
...
                    </configuration>
                </execution>
            </executions>
            <dependencies>
                <dependency>
                    <groupId>com.github.edwgiz</groupId>
                    <artifactId>maven-shade-plugin.log4j2-cachefile-transformer</artifactId>
                    <version>2.1</version>
                </dependency>
            </dependencies>
        </plugin>
</plugins>
pjngdqdw

pjngdqdw3#

当您从ide运行应用程序时,jar会自动运行而不嵌入依赖项,而且日志设置也不会有冲突。但是,当您将应用程序转换为fatjar时,所有依赖项都将被注入到项目的jar文件中,来自外部jar文件(依赖项)的log4j设置可能会发生冲突,而fatjar进程会将它们合并到单个工件中。
在这种情况下,我认为您的“log4j2plugins.dat”文件可能有冲突。当然,您可以使用zip编辑器(例如:7zip)打开您的fatjar文件,如下所示导航到fatjar中的路径,并从您的fatjar中删除一个冲突文件(您可以根据大小选择最小的文件)。运行fatjar并检查日志记录是否正常工作。
\meta inf\org\apache\logging\log4j\core\config\plugins\log4j2plugins.dat
现在我们可以检查依赖项(工件)并找到其中哪些包含“log4j2plugins.dat”文件。因此,您可以从构建工具中排除包含该文件的模块,然后您的fatjar创建过程将排除冲突的文件,并且您的新fatjar可以按预期开始日志记录。
在我的例子中,我的fatjar模块从spring boot导入了一些其他模块,当我排除了冲突的日志库时,我的fatjar开始记录而没有任何错误。 configurations { all*.exclude module: 'spring-boot' all*.exclude module: 'spring-boot-starter-logging' all*.exclude module: 'logback-classic' all*.exclude module: 'commons-logging' }

s4n0splo

s4n0splo4#

在fatjar中,依赖项可以在导致此问题的meta-inf中提供log4j-provider.properties,
在gradle任务中删除它:

task fatJar(type: Jar) {
    manifest {
        attributes 'Implementation-Title': 'project',
        'Implementation-Version': project.version,
        'Main-Class': 'com.sample.CLI'
    }
    baseName = project.name + '-all'
    from {
        configurations.compile.collect {
            it.isDirectory() ? it : zipTree(it).matching {
                exclude 'META-INF/**.RSA'
                exclude 'META-INF/MANIFEST.MF'
                exclude 'META-INF/log4j-provider.properties'
            } } }
    with jar
}
tf7tbtn2

tf7tbtn25#

这个 LoggerContextFactory 将log4japi绑定到其实现。log4j logmanager通过定位的所有示例来定位loggercontextfactory META-INF/log4j-provider.properties ,标准 java.util.Properties 文件,然后检查每个文件,以验证它为log4japiversion属性指定的值是否符合logmanager所需的版本。
对于fatjar,还可以显式指定要使用的log4j2 LoggerContextFactory 在您的申请中:

System.setProperty("log4j2.loggerContextFactory", "org.apache.logging.log4j.core.impl.Log4jContextFactory")

或按照 log4j-provider.properties 文件包含在您的 log4j-core jar。

相关问题