Hadoop MapReduce XML转换任务报错:PipeMapRed.waitOutputThreads()返回码1
问题场景
执行Hadoop MapReduce转换XML文件任务时,Map Task直接失败,错误日志如下:
2023-04-04 09:41:52,515 INFO mapreduce.Job: map 0% reduce 0% 2023-04-04 09:42:12,676 INFO mapreduce.Job: Task Id : attempt_1680592009322_0021_m_000000_0, Status : FAILED Error: java.lang.RuntimeException: PipeMapRed.waitOutputThreads(): subprocess failed with code 1
任务启动命令:
yarn jar /opt/hadoop-3.2.1/share/hadoop/tools/lib/hadoop-streaming-3.2.1.jar \ -file "script/mapper_convert_xml.py" -mapper "python3 mapper_convert_xml.py" \ -file "script/reducer_convert_xml.py" -reducer "python3 reducer_convert_xml.py" \ -input /input/philharmonie_data/AIC94.xml -output /output/philharmonie_data
脚本已添加#!/usr/bin/env python头并设置chmod 744权限,本地通过管道测试可正常执行,但集群运行失败,已尝试调整权限、shebang、分发参数、Python路径等操作无效,怀疑import xml.etree.ElementTree as ET语句导致异常。
排查解决思路
1. 验证集群计算节点的Python XML模块可用性
登录到集群任意计算节点(或TaskManager节点),直接执行以下命令,确认标准库xml.etree.ElementTree是否可用:
python3 -c "import xml.etree.ElementTree as ET; print('模块导入成功')"
若执行报错,说明集群Python环境缺失该模块(虽为标准库,但不排除自定义编译Python时未包含的情况),需同步Python环境或重新编译安装完整Python。
2. 捕获Python脚本的详细错误输出
Hadoop Streaming默认不会将Python的stderr内容输出到Job日志,需修改启动命令将错误重定向到stdout,或在脚本中添加调试代码:
- 修改任务启动命令,给mapper/reducer命令追加错误重定向:
yarn jar /opt/hadoop-3.2.1/share/hadoop/tools/lib/hadoop-streaming-3.2.1.jar \ -file "script/mapper_convert_xml.py" -mapper "python3 mapper_convert_xml.py 2>&1" \ -file "script/reducer_convert_xml.py" -reducer "python3 reducer_convert_xml.py 2>&1" \ -input /input/philharmonie_data/AIC94.xml -output /output/philharmonie_data - 在脚本开头添加调试代码,打印环境信息并捕获导入异常:
import sys # 打印Python版本和路径,确认运行环境 print(f"Python版本: {sys.version}", file=sys.stderr) print(f"模块搜索路径: {sys.path}", file=sys.stderr) # 捕获ET模块导入异常 try: import xml.etree.ElementTree as ET print("xml.etree.ElementTree模块导入成功", file=sys.stderr) except Exception as e: print(f"导入失败原因: {str(e)}", file=sys.stderr) raise
之后查看该失败Task的日志(可通过YARN WebUI或yarn logs -applicationId <app_id>命令获取),就能看到Python脚本的具体错误信息。
3. 验证集群本地的XML文件兼容性
将HDFS上的XML文件下载到集群节点本地,用脚本测试,排除HDFS文件的编码/格式问题:
# 下载HDFS文件到本地临时目录 hdfs dfs -get /input/philharmonie_data/AIC94.xml /tmp/test.xml # 用本地脚本测试 cat /tmp/test.xml | python3 /path/to/mapper_convert_xml.py | python3 /path/to/reducer_convert_xml.py
若本地测试失败,说明文件本身存在编码或格式问题(如换行符、特殊字符),需先处理文件;若测试成功,则问题出在Hadoop任务的运行环境或参数配置。
4. 确认脚本分发与执行路径正确性
- 改用
-files参数(复数)明确指定脚本文件,确保Hadoop正确分发:yarn jar /opt/hadoop-3.2.1/share/hadoop/tools/lib/hadoop-streaming-3.2.1.jar \ -files script/mapper_convert_xml.py,script/reducer_convert_xml.py \ -mapper "python3 mapper_convert_xml.py 2>&1" \ -reducer "python3 reducer_convert_xml.py 2>&1" \ -input /input/philharmonie_data/AIC94.xml -output /output/philharmonie_data - 确认提交任务时,
script/是当前工作目录下的相对路径,若路径错误,Hadoop无法找到脚本导致分发失败。
5. 锁定Python执行路径的一致性
集群节点的Python路径可能与本地不同,先在集群节点上查找python3的绝对路径:
which python3
然后在任务启动命令中替换为绝对路径,避免环境变量差异导致的路径问题:
# 假设集群python3绝对路径为/usr/local/bin/python3 yarn jar /opt/hadoop-3.2.1/share/hadoop/tools/lib/hadoop-streaming-3.2.1.jar \ -file "script/mapper_convert_xml.py" -mapper "/usr/local/bin/python3 mapper_convert_xml.py 2>&1" \ -file "script/reducer_convert_xml.py" -reducer "/usr/local/bin/python3 reducer_convert_xml.py 2>&1" \ -input /input/philharmonie_data/AIC94.xml -output /output/philharmonie_data
内容的提问来源于stack exchange,提问作者leo

