You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Spark Submit提交Jar至YARN时Log4j2无法生成本地/HDFS日志

解决Spark on YARN下Log4j2生成独立日志文件的问题

我来帮你搞定这个问题——在YARN上跑Spark应用时,自定义Log4j2日志总是不生成,大概率是路径适配、配置加载或者依赖冲突的问题,我给你一步步拆解解决:

1. 先把Log4j2的路径配置适配YARN容器

你直接写本地绝对路径肯定不行,YARN的容器和你提交任务的机器是完全隔离的,容器里根本没有你本地的目录。这里有两种靠谱的配置方式:

方式一:写到YARN容器的日志目录(方便通过YARN聚合查看)

在你的log4j2.xml里用YARN内置的系统变量指定路径,这样日志会直接写到每个容器的专属日志目录:

<Appenders>
    <File name="AppFileAppender" fileName="${sys:spark.yarn.app.container.log.dir}/my-custom-app.log">
        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
    </File>
</Appenders>
<Loggers>
    <Root level="info">
        <AppenderRef ref="AppFileAppender"/>
    </Root>
</Loggers>

后续你可以用yarn logs -applicationId <你的应用ID>查看所有容器的日志,包括这个自定义文件。

方式二:写到HDFS(统一存储日志)

如果想把日志统一存在HDFS,用RollingFileAppender配合HDFS路径(注意要确保Spark有HDFS依赖):

<Appenders>
    <RollingFile name="HdfsRollingAppender" 
                 fileName="hdfs:///user/your-username/app-logs/my-app.log"
                 filePattern="hdfs:///user/your-username/app-logs/my-app-%d{yyyy-MM-dd}-%i.log.gz">
        <PatternLayout pattern="%d{yyyy-MM-dd HH:mm:ss} %-5p %c{1}:%L - %m%n"/>
        <Policies>
            <SizeBasedTriggeringPolicy size="100MB"/>
        </Policies>
        <DefaultRolloverStrategy max="10"/>
    </RollingFile>
</Appenders>

提前用HDFS命令创建好目录并赋权:

hdfs dfs -mkdir -p /user/your-username/app-logs
hdfs dfs -chmod 775 /user/your-username/app-logs

2. 修正Spark Submit命令的参数

你用--files上传配置文件的方式不对,还要明确告诉Spark加载这个自定义配置,覆盖默认的日志设置。正确的提交命令应该是这样:

spark-submit \
  --class com.your.package.YourMainClass \
  --master yarn \
  --deploy-mode cluster \
  --files ./log4j2.xml#log4j2.xml \  # 给上传的文件加别名,方便容器内引用
  --driver-java-options "-Dlog4j.configurationFile=log4j2.xml" \  # 驱动端用自定义配置
  --conf spark.executor.extraJavaOptions="-Dlog4j.configurationFile=log4j2.xml" \  # executor端用自定义配置
  your-built-app.jar

这里的#log4j2.xml是关键——它会把你本地的log4j2.xml上传到容器后,仍然用这个名字保存,这样-Dlog4j.configurationFile才能找到它。

3. 排除Spark自带的Log4j依赖,避免版本冲突

Spark默认自带Log4j相关依赖,很可能和你自己引入的Log4j2版本冲突,导致配置不生效。在你的pom.xml里排除Spark的Log4j依赖:

<dependency>
    <groupId>org.apache.spark</groupId>
    <artifactId>spark-core_2.12</artifactId>
    <version>3.3.0</version> <!-- 换成你的Spark版本 -->
    <scope>provided</scope>
    <exclusions>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-core</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.apache.logging.log4j</groupId>
            <artifactId>log4j-api</artifactId>
        </exclusion>
        <exclusion>
            <groupId>org.slf4j</groupId>
            <artifactId>slf4j-log4j12</artifactId>
        </exclusion>
    </exclusions>
</dependency>

同时确保你自己的Log4j2依赖是完整的:

<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-core</artifactId>
    <version>2.17.2</version> <!-- 选一个稳定的版本 -->
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-api</artifactId>
    <version>2.17.2</version>
</dependency>
<dependency>
    <groupId>org.apache.logging.log4j</groupId>
    <artifactId>log4j-slf4j-impl</artifactId>
    <version>2.17.2</version> <!-- 适配SLF4J桥接 -->
</dependency>

4. 验证配置是否被正确加载

在你的主类里加一行代码,打印当前Log4j2的配置文件路径,确认是否加载了正确的文件:

import org.apache.logging.log4j.core.LoggerContext;

public class YourMainClass {
    public static void main(String[] args) {
        // 打印Log4j2配置路径
        LoggerContext context = (LoggerContext) org.apache.logging.log4j.LogManager.getContext(false);
        System.out.println("Loaded Log4j2 config file: " + context.getConfiguration().getConfigurationSource().getLocation());
        
        // 你的Spark应用代码...
        SparkSession spark = SparkSession.builder()
                .appName("YourAppName")
                .getOrCreate();
        // ...
    }
}

提交应用后,用yarn logs -applicationId <你的应用ID>查看日志,如果看到打印的路径是你上传的log4j2.xml,说明配置加载成功了。

5. 检查权限问题

如果还是没生成日志,检查一下:

  • 写本地路径时:YARN容器对该目录有没有读写权限(尽量用前面说的spark.yarn.app.container.log.dir,这个目录是容器自带的,权限没问题)
  • 写HDFS路径时:运行Spark的用户对HDFS目录有没有读写权限(用hdfs dfs -ls /user/your-username/app-logs确认)

按照这些步骤来,应该就能解决你的问题了!

内容的提问来源于stack exchange,提问作者Mohit

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.25 07:48:46