hadoop streaming 是 hadoop 的一個多語言編程框架灭衷。關(guān)于 streaming 的使用方法可以參見 streaming 的官方文檔橡疼。一些比較高級的用法男翰,例如加載詞典闷袒,使用計數(shù)器等致盟,也可以在網(wǎng)上找到答案腥泥。下面是在使用 streaming 的時候踩到的一些坑匾南,記錄一下。
1蛔外,生成本地的 tmp file
hadoop streaming 工作的時候會將要上傳的文件打包并上傳蛆楞。在客戶端機器上,hadoop client 會將 -file
選項指定的文件拷貝到某個臨時目錄下夹厌,并且進行打包程序豹爹。所以,要求當前用戶需要對這個臨時目錄具有寫權(quán)限矛纹。常常遇到的錯誤是臂聋,當前用戶對這個目錄沒有寫權(quán)限,在提交任務(wù)的時候會報告如下的錯誤:
Exception in thread "main" java.io.IOException: permission denied
at java.io.UnixFileSystem.createFileExclusively(Native Method)
at java.io.File.createTempFile(File.java:1879)
at org.apache.hadoop.util.RunJar.main(RunJar.java:115)
這個臨時目錄一般在hadoop 配置文件中的 core-site.xml 和 mapred-site.xml 中指定或南。一般來說孩等,保證hadoop.tmp.dir
和mapred.temp.dir
所指向的目錄具有寫權(quán)限就足夠了。如果不想修改 core-site.xml 和 mapred-site.xml采够,可以在提交 streaming job 的時候通過-D選項來指定:
hadoop jar hadoop/contrib/streaming/hadoop-streaming-1.2.0-w1.2.0.jar \
-Dhadoop.tmp.dir=~/tmp/ \
-Dmapred.temp.dir=~/tmp/ \
-mapper "cat"
-reducer "wc"
....
2肄方,多路輸出并不是在每個版本都可用。
hadoop streaming 中 reducer 的輸出文件類似:${outputDir}/part-******
蹬癌,其中 ***** 是 reducer 任務(wù)的任務(wù)號权她。但有的時候我們希望 reducer 能夠輸出到多路文件,例如逝薪,對于文件符合某個條件的隅要,輸出到 part-*****-A,其余的輸出到 part-*****-B董济。
hadoop-v2-u7 的版本為 streaming 引入了兩個多路輸出的插件:SuffixMultipleTextOutputFormat和SuffixMultipleSequenceFileOutputFormat步清。如果要直接使用這兩個插件,需要保證客戶端和服務(wù)器上的 hadoop 版本均為 hadoop-v2-u7 或者更高感局。使用這兩個插件的教程可以參見hadoop streaming實戰(zhàn):多路輸出尼啡。
需要特別注意的一點是:很多 hadoop 發(fā)行版暂衡,即使是最近的發(fā)行版询微,也未必有這兩個插件(比如 cloudera 的發(fā)行版——當然也許是我的版本還不夠高)崖瞭。確定有沒有這兩個插件的一種方法是看一下這個發(fā)行版的 API 文檔有沒有 org.apache.hadoop.mapred.lib.SuffixMultipleTextOutputFormat 這個類即可(或者直接查看 HADOOP_CLASSPATH)。
如果沒有這個類撑毛,需要自己定制一個 MultipleTextOutputFormat(用java)书聚。定制的方法可以參考hadoop多路輸出。
3藻雌,/etc/fstab 為 noexec 掛載導致 permission denied
如果 streaming 的 mapper和 reducer 使用的是二進制文件雌续,那么在 mapper 和 reducer 中常常需要這樣調(diào)用:
hadoop jar hadoop/contrib/streaming/hadoop-streaming-1.2.0-w1.2.0.jar \
-Dhadoop.tmp.dir=~/tmp/ \
-Dmapred.temp.dir=~/tmp/ \
-mapper "./mymapper" \
-reducer "./myreducer" \
-file "./mymapper" \
-file "./myreducer" \
....
不幸的是,很多時候這樣調(diào)用的時候往往會出現(xiàn)如下的錯誤:
Caused by: java.io.IOException: java.io.IOException: error=13, Permission denied
at java.lang.UNIXProcess.<init>(UNIXProcess.java:148)
at java.lang.ProcessImpl.start(ProcessImpl.java:65)
at java.lang.ProcessBuilder.start(ProcessBuilder.java:453)
... 24 more
這個往往是因為胯杭,streaming 需要把二進制文件分發(fā)到每臺節(jié)點機器上驯杜,創(chuàng)建一個臨時目錄,把二進制文件放到這個臨時目錄里然后開始運行做个。這個臨時目錄一般在 hadoop 的數(shù)據(jù)磁盤上鸽心,通過 /etc/fstab 掛在到計算借點的機器,而很多時候為了安全起見居暖,這個掛載常常指定了 noexec 的屬性:
/home/disk4 ext4 noexec,nosuid,noatime 1 2 UUID="0cbe17e7-4c00-4409-824c-d84e6a80fb5d" /home/disk5 ext4
解決這個問題的方法有:
- 刪除 noexec 屬性顽频;
- 使用一個 shell 腳本包裝一個 shell 腳本先將二進制文件拷貝到 /tmp 等目錄,然后再執(zhí)行:
#!/bin/sh
cp ./mymapper /tmp/
/tmp/mymapper
然后指定--mapper "sh mapper.sh"
來提交任務(wù)太闺。