Hadoop Streaming如何传文件夹到集群

上传文件夹着实让我蛋疼了阵。

以Hadoop的Streaming官方文档为例,研究一下Hadoop任务工作目录的目录结构。Hadoop官方例子如下 (最好自己看文档,血的教训):

$HADOOP_HOME/bin/hadoop  jar $HADOOP_HOME/hadoop-streaming.jar \
                  -archives 'hdfs://hadoop-nn1.example.com/user/me/samples/cachefile/cachedir.jar' \  
                  -D mapred.map.tasks=1 \
                  -D mapred.reduce.tasks=1 \ 
                  -D mapred.job.name="Experiment" \
                  -input "/user/me/samples/cachefile/input.txt"  \
                  -output "/user/me/samples/cachefile/out" \  
                  -mapper "xargs cat"  \
                  -reducer "cat"  

$ ls test_jar/
cache.txt  cache2.txt

$ jar cvf cachedir.jar -C test_jar/ .
added manifest
adding: cache.txt(in = 30) (out= 29)(deflated 3%)
adding: cache2.txt(in = 37) (out= 35)(deflated 5%)

$ hadoop dfs -put cachedir.jar samples/cachefile

$ hadoop dfs -cat /user/me/samples/cachefile/input.txt
cachedir.jar/cache.txt
cachedir.jar/cache2.txt

$ cat test_jar/cache.txt 
This is just the cache string

$ cat test_jar/cache2.txt 
This is just the second cache string

$ hadoop dfs -ls /user/me/samples/cachefile/out      
Found 1 items
/user/me/samples/cachefile/out/part-00000  <r 3>   69

$ hadoop dfs -cat /user/me/samples/cachefile/out/part-00000
This is just the cache string   
This is just the second cache string
这个例子跑起来是没有问题的。

这里的内容稍稍有一些难理解。什么叫别名?类似于C语言中的引用。比如我有一个文件(or文件夹)叫做file,把他打包成file.jar后put到hadoop,之前在streaming时使用archives引用,这时候hadoop会在每个任务的当前工作目录创建一个名为file.jar的symlink指向“真正”的file.jar,然后在工作目录自动解决此file.jar,注意file.jar解压后并不会得到file这个东西(与本地不同),而是得到file.jar/file,即自动的添加了一级目录file.jar。可是目录file.jar可读性太差,于是我们希望给他一个别名,比如叫做data。那么在执行streaming时就要写为

-archives /*/file.jar#data

如果在工作目录解压后得到的文件就是data/file(注意data只是file.jar的一个别名,file.jar/file也是存在的)

比如上例中,在任务的工作目录cachedir.jar解压后的目录结构是cachedir.jar/cache.txt cache2.txt,这是因为我们使用jar压缩的时候加了-C选项,因而忽略了目录。

下面我们稍稍修改上面例子,使用下面的命令压缩:

jar cvf cachedir.jar test_jar/ .

此时本地解压cachedir.jar得到的是test_jar/cache.txt cache2.txt

此时上面的例子就无法执行了,得到如下的错误:

attempt_201403291230_171885_m_000001_0: cat: cachedir.jar/cache.txt: No such file or directory

attempt_201403291230_171885_m_000001_0: cat: cachedir.jar/cache2.txt: No such file or directory

reduce仍试图去cachedir.jar下找文件,实际上在任务的工作目录下目录结构已经变成了

cachedir.jar/test_jar/cache.txt cache2.txt

自然找不到了。

我们修改index.txt的内容为如下两行

cachedir.jar/test_jar/cache.txt

cachedir.jar/test_jar/cache2.txt

程序便又可以运行了

当然,看到cachedir.jar作为目录肯定不爽,于是我们可以给他设一个别名

-archives /*/cachedir.jar#data

然后目录就“变成”了data/test_jar/cache.txt cache2.txt

搞定!


我们可以用一个脚本验证:

run_mapred.sh

ls * >$2
"cat"
然后streaming命令改为:

hadoop jar $streaming_jar \
            -archives 'hdfs:///user/tinfo/cuixiangfei/test2/cachedir.jar' \
            -D mapred.job.name="Experiment" \
            -files ./run_mapred.sh \
            -numReduceTasks 1 \
            -input "/user/tinfo/cuixiangfei/test2/index.txt" \
            -output $output_path \
            -mapper /bin/cat \
            -reducer "sh run_mapred.sh"

这是一个更简单的任务,map和reduce都是cat。我们只是为了看run_mapred.sh中ls的输出,如下:

job.jar
run_mapred.sh

cachedir.jar:
cachedir.jar
META-INF
test_jar

tmp:

可以看到,除了job.jar外,还有-files的run_mapred.sh,cachedir.jar下面有cachedir.jar、META_INF和test_jar,test_jar下就是我们的数据cache.txt和cache2.txt。

由上说明,多个文件被压缩成XXXX.jar后,在任务的工作目录自动解压时是解压成XXXX.jar/(这里才是我们的数据),多了一层目录。比如a.txt, b.txt, c.txt打包成XXXX.jar,解压后就是XXXX.jar/a.txt....,并不会像我之前想的那样把a.txt, b.txt, c.txt解压到当前目录。

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值