Spark-submit任务调用saveAsTextFile时输出目录已存在报错求助
看起来你遇到了一个挺棘手的Spark on YARN + Conda环境下的输出问题,我帮你梳理下可能的原因和解决办法:
问题核心分析
从你的描述和错误日志来看,最矛盾的点是:明明提交任务前输出路径是空的,但执行saveAsTextFile时却触发了FileAlreadyExistsException,而且路径还被自动创建并生成了_temporary目录。这大概率和Spark在YARN集群模式下的文件输出流程、权限配置或者Conda环境的依赖一致性有关,具体拆解如下:
1. 驱动与Executor的HDFS权限/身份不匹配
在YARN cluster模式下,Driver运行在NodeManager节点上,而Executor分布在其他节点。如果两者的运行身份存在权限差异,就可能出现这种情况:
- Driver成功创建了输出目录和
_temporary子目录 - Executor尝试写入临时文件时因权限不足直接失败,导致任务中断
- 后续Spark的检查逻辑发现输出目录已经存在,就抛出了异常
2. Conda环境的Hadoop/Spark依赖和集群不兼容
你用了自定义的Conda环境,很可能环境里的依赖版本和集群的Cloudera版本不匹配:
- 比如你在Conda里装了自己的
pyspark或hadoop包,版本和集群提供的不一致 - 这种版本冲突会导致Executor在处理HDFS文件操作时出错,没法正常写入临时文件,任务失败后目录就残留下来了
3. Spark输出目录检查的时机异常
Spark的FileOutputFormat.checkOutputSpecs方法会严格校验输出目录是否存在。在某些复杂的集群配置下,可能Driver在触发检查前就提前创建了目录,导致检查步骤误判目录已存在(这个情况相对少见,但也值得排查)
针对性解决方案
你可以按以下步骤逐一排查解决:
1. 验证并统一HDFS权限
- 先确认Driver和Executor的运行身份:去YARN的ApplicationMaster日志里看Driver的启动用户,再查已启动的Executor日志(哪怕只启动了一个),确认两者用户是否一致
- 检查输出目录所在HDFS路径的权限:执行以下命令确认你有完整的读写执行权限:
hdfs dfs -lsd /user/yolo/ hdfs dfs -getfacl /user/yolo/ - 如果权限有问题,用
hdfs dfs -chmod或hdfs dfs -chown调整,确保任务运行用户能自由操作该路径
2. 让Conda环境适配集群依赖
- 别在Conda环境里单独装
pyspark!直接用集群提供的Spark版本:执行pip uninstall pyspark移除Conda里的本地版本,强制使用集群的Spark依赖(你的提交命令已经指定了集群Spark路径,这样能避免版本冲突) - 检查Conda环境的Java版本:从错误日志看集群用的是Java 8,确保你的Conda环境里的Java也是8,版本不兼容也会导致HDFS操作出问题
3. 临时调整Spark检查配置(应急用)
如果前面的排查都没问题,可以先试试跳过输出目录的存在性检查(注意:这个方案只适合临时验证,别长期用,会覆盖已有数据):
- 在你的
spark-submit命令里加这个配置:--conf spark.hadoop.validateOutputSpecs=false - 这个配置会让Spark忽略目录已存在的异常,直接写入,能帮你验证是不是检查逻辑导致的问题
4. 手动清理残留目录后重试
每次任务失败后,先手动删掉残留的输出目录:
hdfs dfs -rm -r hdfs://ddsco-nameservice/user/yolo/arrowcom_result/
然后重新提交任务,看看还会不会出现同样的问题
额外小建议
- 仔细看Executor日志:哪怕其他Executor没启动,也看看已经启动的那个的日志,说不定里面有HDFS写入失败的详细信息,能直接定位核心问题
- 写个极简测试任务:比如直接生成一个简单的RDD然后
saveAsTextFile,用同样的Conda环境和提交命令运行,先排除业务逻辑的问题
内容的提问来源于stack exchange,提问作者B.Mr.W.
相关产品推荐
相关产品推荐

