log4j2错误:StatusLogger未识别的转换说明符

60

我在我的项目中使用了log4j2,在intellij Idea中运行main方法时,正确地打印日志。

当我使用maven-shade-plugin将项目打包成jar文件,并作为独立应用程序运行时,出现了错误:

java -cp package.jar com.xxx.TestMain

控制台输出如下:

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 Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.
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 Unrecognized format specifier [level]
ERROR StatusLogger Unrecognized conversion specifier [level] starting at position 35 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [logger]
ERROR StatusLogger Unrecognized conversion specifier [logger] starting at position 47 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [msg]
ERROR StatusLogger Unrecognized conversion specifier [msg] starting at position 54 in conversion pattern.
ERROR StatusLogger Unrecognized format specifier [n]
ERROR StatusLogger Unrecognized conversion specifier [n] starting at position 56 in conversion pattern.

pom.xml配置,log4j2版本为2.10.0,Spring Boot版本为1.5.9.RELEASE

<dependencies>
    <dependency>
        <groupId>org.springframework.boot</groupId>
        <artifactId>spring-boot-starter</artifactId>
        <exclusions>
            <exclusion>
                <groupId>org.springframework.boot</groupId>
                <artifactId>spring-boot-starter-logging</artifactId>
            </exclusion>
        </exclusions>
    </dependency>
    <dependency>
        <groupId>org.slf4j</groupId>
        <artifactId>slf4j-api</artifactId>
        <version>1.7.25</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-slf4j-impl</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-api</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
    <dependency>
        <groupId>org.apache.logging.log4j</groupId>
        <artifactId>log4j-core</artifactId>
        <version>${log4j2.version}</version>
    </dependency>
</dependencies>
<build>
    <plugins>
        <plugin>
            <groupId>org.apache.maven.plugins</groupId>
            <artifactId>maven-shade-plugin</artifactId>
            <version>3.1.0</version>
            <configuration>
                <createDependencyReducedPom>false</createDependencyReducedPom>
            </configuration>
            <executions>
                <execution>
                    <phase>package</phase>
                    <goals>
                        <goal>shade</goal>
                    </goals>
                    <configuration>
                        <transformers>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.handlers</resource>
                            </transformer>
                            <transformer implementation="org.apache.maven.plugins.shade.resource.AppendingTransformer">
                                <resource>META-INF/spring.schemas</resource>
                            </transformer>
                        </transformers>
                        <filters>
                            <filter>
                                <artifact>*:*</artifact>
                                <excludes>
                                    <exclude>META-INF/*.SF</exclude>
                                    <exclude>META-INF/*.DSA</exclude>
                                    <exclude>META-INF/*.RSA</exclude>
                                </excludes>
                            </filter>
                        </filters>
                    </configuration>
                </execution>
            </executions>
        </plugin>
        <plugin>
            <artifactId>maven-compiler-plugin</artifactId>
            <configuration>
                <source>1.8</source>
                <target>1.8</target>
            </configuration>
        </plugin>
    </plugins>
    <resources>
        <resource>
            <directory>src/main/resources</directory>
        </resource>
    </resources>
    <sourceDirectory>src/main/java</sourceDirectory>
</build>

log4j2.xml配置文件

<?xml version="1.0" encoding="UTF-8"?>
<Configuration status="debug" monitorInterval="30" shutdownHook="disable">
    <properties>
        <property name="LOG_HOME">/data1/logs</property>
        <property name="JOB_NAME">noname</property>
    </properties>
    <Appenders>
        <Console name="Console" target="SYSTEM_OUT">
            <PatternLayout pattern="%date{yyyy-MM-dd HH:mm:ss} [%t] %level [%logger{36}][%file:%line] %msg%n%throwable"/>
        </Console>

        <RollingRandomAccessFile name="DetailFile"
                                 fileName="${sys:LOG_HOME}/${sys:JOB_NAME}/detail.log" bufferedIO="false"
                                 filePattern="${sys:LOG_HOME}/${sys:JOB_NAME}/detail.%d{yyyy-MM-dd}-%i.log">

            <PatternLayout
                    pattern="%date{yyyy-MM-dd HH:mm:ss} [%t] %level [%file:%line] %msg%n%throwable"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
                <SizeBasedTriggeringPolicy size="500 MB"/>
            </Policies>
        </RollingRandomAccessFile>
        <RollingRandomAccessFile name="error"
                                 fileName="${sys:LOG_HOME}/${sys:JOB_NAME}/error.log" bufferedIO="true"
                                 filePattern="${sys:LOG_HOME}/${sys:JOB_NAME}/error.%d{yyyy-MM-dd}.log">

            <PatternLayout
                    pattern="%date{yyyy-MM-dd HH:mm:ss} [%t] %level [%logger{36}:%line] %msg%n%throwable"/>
            <Policies>
                <TimeBasedTriggeringPolicy interval="1" modulate="true"/>
            </Policies>
        </RollingRandomAccessFile>
    </Appenders>
    <Loggers>
        <Root level="info">
            <AppenderRef ref="DetailFile"/>
            <AppenderRef level="error" ref="error"/>
        </Root>
    </Loggers>
</Configuration>

1
你想在这里提问。我看到了一个错误,但没有问题。 - Ctznkane525
1
我想知道如何解决这个错误。 - CoderMeng
1
在Java 11中,由于区域设置的问题,我们遇到了类似的问题-请参见https://issues.apache.org/jira/browse/LOG4J2-2435。 - mkobit
9个回答

97

如果一个依赖包含log4j2插件,则会在jar中包含一个Log4j2Plugins.dat缓存文件。当使用Maven shade插件将多个带有Log4j2Plugins.dat文件的jar合并时,只有一个会生效。没有插件定义,启动时会显示错误。Log4j2问题

解决此问题的一种方法是从阴影jar中排除Log4j2Plugins.dat缓存文件,以便Log4j在启动时扫描插件。为此,在您的pom中的maven-shade-plugin配置中添加过滤器:

<plugin>
  <groupId>org.apache.maven.plugins</groupId>
  <artifactId>maven-shade-plugin</artifactId>
  <version>3.1.0</version>
  <configuration>
    <createDependencyReducedPom>false</createDependencyReducedPom>
    <filters>
      <filter>
        <artifact>*:*</artifact>
        <excludes>
          <exclude>**/Log4j2Plugins.dat</exclude>
        </excludes>
      </filter>
    </filters>
  </configuration>
  <!-- ... -->
</plugin>

另一个解决方案是使用一个特定于log4j版本的转换插件合并缓存文件。

6
将这个配置添加到pom.xml中的maven-shade-plugin条目中,解决了我的问题。 - Bertware
请查看下面的评论以获取有关Gradle的信息。 - MaX
1
如何在Scala中修复这个问题? - Suchita
你好,上述提到的解决方案都没有解决我的问题。唯一有用的方法是不要最小化UBER jar文件。 - experiment unit 1998X
1
添加Log4j2PluginCacheFileTransformer解决了我的问题。请注意,该插件最近刚刚捐赠给了Apache软件基金会,因此最新版本可以在Apache GitHub网站上的Log4j Plugin Cache Transformer找到。该页面有示例代码。 - undefined
添加Log4j2PluginCacheFileTransformer解决了我的问题。请注意,该插件最近刚刚捐赠给了Apache软件基金会,因此最新的版本可以在Apache GitHub网站上找到Log4j Plugin Cache Transformer。该页面有示例代码。 - Garret Wilson

26
如果你正在使用Gradle和ShadowJar 4+:
shadowJar {
  transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer)
}

Gradle Kotlin DSL:

shadowJar {
  transform(com.github.jengelman.gradle.plugins.shadow.transformers.Log4j2PluginsCacheFileTransformer::class.java)
}

1
这对我很有效!谢谢! - MaX

14

不幸的是,我不能回复Shashank Kapoor的答案,因为他正确指出排除 Log4j2Plugins.dat 文件可以解决这个问题。在使用gradle时,这对我有用:

shadowJar {
    exclude "**/Log4j2Plugins.dat"
}

虽然这样可以避免格式错误,但现在应用程序无法启动:Exception in thread "main" java.util.ServiceConfigurationError: java.nio.file.spi.FileSystemProvider: Provider org.apache.sshd.sftp.client.fs.SftpFileSystemProvider not found。 - Charlie
不确定是否与原始问题有关,但是我能够通过从shadowJar中排除其清单来解决SftpFileSystemProvider错误:exclude(“META-INF / services / java.nio.file.spi.FileSystemProvider”) - Charlie

6

我以前曾经见过这个错误,当时是因为系统上存在多个版本的Log4j2。


1
我检查了Maven包日志,只有Log4j2版本。 - CoderMeng
1
请确保从您的应用程序中打印系统属性java.classpath的值。这可能是一个短暂的依赖项或其他配置。 - Remko Popma

4

对于我们中的一些人来说,为了纠正Log4Shell(CVE-2021-44228)漏洞,正在从我们的类路径中删除旧的Logj42,升级后使用你的超级jar时可能会出现此问题。

如果您是从Maven或Gradle构建您的超级jar,请分别使用以下插件之一:

如果您是通过其他方式构建它们的,请参阅此答案:https://dev59.com/QK_2oIgBc1ULPQZF43V7#70497498。但基本上您必须像这个类一样正确处理Log4j2插件缓存文件:

https://github.com/edwgiz/maven-shaded-log4j-transformer/blob/master/src/main/java/io/github/edwgiz/log4j/maven/plugins/shade/transformer/Log4j2PluginCacheFileTransformer.java

在构建新的uber jar时,正确处理Log4j2Plugins.dat文件。


1
在我们的项目中,在创建TestAppender类之后出现了这样一个问题。
@Plugin(name = "TestAppender", category = Core.CATEGORY_NAME, elementType = Appender.ELEMENT_TYPE)
public class TestAppender extends AbstractAppender {
...

它的设置覆盖了Log4j2Plugins.dat文件中的记录器设置。

然后我们将其移动到一个单独的模块,并以类似的方式将其附加到项目中(请注意范围):

<dependency>
  <groupId>info.project</groupId>
  <artifactId>test</artifactId>
  <version>1.0-SNAPSHOT</version>
  <scope>test</scope>
</dependency>

0

您可以排除所有的Log4j2Plugins.dat文件,除了正确的那一个,即包含在log4j-core中的那个:

<filter>
    <artifact>SOME-ARTIFACT</artifact>
    <excludes>
        <exclude>**/Log4j2Plugins.dat</exclude>
    </excludes>
</filter>
<filter>
    <artifact>SOME-ARTIFACT</artifact>
    <excludes>
        <exclude>**/Log4j2Plugins.dat</exclude>
    </excludes>
</filter>
...

请查看此处答案,包括一个示例项目:https://dev59.com/f662pogBymzxlkE8Xf-Z#76003471


0
@PowerMockIgnore( {"org.springframework.util.Log4jConfigurer","javax.script.*","javax.management.*", "org.w3c.dom.*", "org.apache.log4j.*","org.apache.logging.*","org.apache.commons.logging.*", "org.xml.sax.*",   "javax.xml.*"})

将此代码片段添加到测试类中。不再有错误日志。


这可能只在使用PowerMock时有用。 - gic186

0

这个链接对我有效。在 shading log4j 时出现了问题。

<filter>
    <artifact>log4j:log4j</artifact>
    <includes>
        <include>org/apache/log4j/spi/LoggingEvent.class</include>
    </includes>
</filter>
<filter>
    <artifact>org.apache.logging.log4j:log4j-*</artifact>
    <includes>
        <include>**</include>
    </includes>
</filter>

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接