在利用hadoop-stream工具发布python任务时很容易出现'subprocess failed with code 1'错误,一般这种错误都是因为Datanode在执行python脚本时发生异常导致。比较常见的是python脚本执行中发生了一些错误,这种可以通过增加try语句解决,另外最常见的就是缺失第三方库了。
缺失第三方库最简单的解决方法当然是在所有的Datanode中部署同样的python解释器——这种方法在小集群下可行,但集群节点数量上来后每当增加新库或更新python版本时就变成了繁琐又耗时的工作。而且如果有一个节点的python解释器出了问题排查起来也是相当恼人。
在之前的工作中,尝试了网上提到的virtualenv打包python解释器然后通过hadoop-stream的-archives选项把打包好的python解释器分发到每个执行节点中,然后指定使用这个解释器执行python脚本,节点就会自动解压这些包并执行相应脚本。
而在实际使用中发现打包的python解释器在测试环境没问题,到了实际的集群上就报错,排除了数据和脚本原因后怀疑还是python解释器运行有问题。把打包的python解释器传到服务器解包运行发现原来是lib文件夹下缺少了一些基础python库,这些库在virtualenv创建的环境中都是以软链接的形式保存的,所以当打包的python解释器在其他服务器上运行(如服务器上的python版本不同或没有python解释器或路径不同)这些软链接就会失效导致python解释器运行出错。解决办法有2种:
一、利用conda来创建一个python解释器的环境,也是本文推荐的方法
这种方法的好处在于可以指定安装任意python版本和第三方库,不像virtualenv一样是在原环境中复制python解释器然后再通过pip来安装第三方库,打包后移植性要来的更好一点。
举一个例子:
1.新建一个环境:
conda create -n test python=2.7.12 numpy pandas
2.打包,环境文件一般在conda目录的envs文件夹中,可通过conda env list查看:
tar cf test.tar test
3.用hadoop-stream提交任务:
hadoop jar /usr/lib/hadoop/hadoop-streaming.jar \
-archives test.tar \
-input /user/testfiles \
-output /user/result \
-mapper "test.tar/test/bin/python mapper.py" \
-file mapper.py \
-reducer"test.tar/test/bin/python reducer.py" \
-file reducer.py
二、用virtualenv新建环境时不用软链接
按照官方文档,似乎在virtualenv命令后加入--always-copy选项则表示不使用软链接,但实际使用时会出错,不知道是否和我的测试环境有关系(CentOS Linux release 7.2.1511,python2.7.5),一定要再加入--no-setuptools --no-pip --no-wheel才能成功创建环境,但没有这些工具安装第三方库很不方便,希望能有大神可以解决这一问题。