
# Spark on Yarn的client模式下spark-submit提交任务出现FileNotFoundException异常
#### 问题
在omm用户（非root用户）下，通过spark-submit提交yarn-client模式的任务，会出现FileNotFoundException异常，任务还能继续执行，但无法查看Driver端日志。例如：执行命令 spark-submit --class org.apache.spark.examples.SparkPi --master yarn-client /opt/client/Spark/spark/examples/jars/spark-examples_2.11-2.2.1-mrs-1.7.0.jar ，结果如下图所示。
![](https://support.huaweicloud.com/devg-mrs/zh-cn_image_0250982816.png)
#### 回答
**原因分析：**
在yarn-client模式下执行任务时，Spark的Driver程序在本地执行；其中通过-Dlog4j.configuration=./log4j-executor.properties配置了Driver的日志文件，log4j-executor.properties配置文件设置日志输出到${spark.yarn.app.container.log.dir}/stdout文件中，由于Spark Driver在本地执行时${spark.yarn.app.container.log.dir}没有设置即为空，则输出目录为/stdout，而非root用户下，在根目录下面没有创建和修改stdout的权限，就会报FileNotFoundException异常。而在yarn-cluster模式下执行任务时，Spark的Driver程序在Application Master下执行，而在Application Master启动时就会通过-D${spark.yarn.app.container.log.dir}设置了输出目录，因此在yarn-cluster模式执行任务不会报FileNotFoundException异常。
**处理方法：**
注：下面所说的$SPARK_HOME默认是/opt/client/Spark/spark。
解决方案1：手动切换日志配置文件。修改文件$SPARK_HOME/conf/spark-defaults.conf中spark.driver.extraJavaOptions的配置项-Dlog4j.configuration=./log4j-executor.properties（默认情况下为./log4j-executor.properties），在yarn-client模式下，修改为-Dlog4j.configuration=./log4j.properties，在yarn-cluster模式下修改为-Dlog4j.configuration=./log4j-executor.properties。
解决方案2：修改启动脚本$SPARK_HOME/bin/spark-class。在spark-class脚本#!/usr/bin/env bash下面添加。
```
# Judge mode: client and cluster; Default: client
argv=`echo $@ | tr [A-Z] [a-z]`
if [[ "$argv" =~ "--master" ]];then
    mode=`echo $argv | sed -e 's/.*--master //'`
    master=`echo $mode | awk '{print $1}'`
    case $master in
    "yarn")
        deploy=`echo $mode | awk '{print $3}'`
        if [[ "$mode" =~ "--deploy-mode" ]];then
                deploy=$deploy
        else
                deploy="client"
        fi
    ;;
  "yarn-client"|"local")
        deploy="client"
    ;;
    "yarn-cluster")
        deploy="cluster"
    ;;
    esac
else
    deploy="client"
fi
# modify the spark-defaults.conf
number=`sed -n -e '/spark.driver.extraJavaOptions/=' $SPARK_HOME/conf/spark-defaults.conf`
if [ "$deploy"x = "client"x ];then
    `sed -i "${number}s/-Dlog4j.configuration=.*properties /-Dlog4j.configuration=.\/log4j.properties /g" $SPARK_HOME/conf/spark-defaults.conf`
else
    `sed -i "${number}s/-Dlog4j.configuration=.*properties /-Dlog4j.configuration=.\/log4j-executor.properties /g" $SPARK_HOME/conf/spark-defaults.conf`
fi
```
这些脚本行的功能和解决方案1类似，通过判断yarn的模式来修改文件$SPARK_HOME/conf/spark-defaults.conf中spark.driver.extraJavaOptions的配置项-Dlog4j.configuration=./log4j-executor.properties。
