2012-07-28 45 views
13

我正在使用Hadoop,我需要找到Hadoop文件系統中的〜100個文件中的哪一個包含某個字符串。在Hadoop文件系統中的多個文件的grep

我可以看到我想要搜索這樣的文件:

bash-3.00$ hadoop fs -ls /apps/mdhi-technology/b_dps/real-time 

..這將返回這樣幾項內容:

-rw-r--r-- 3 b_dps mdhi-technology 1073741824 2012-07-18 22:50 /apps/mdhi-technology/b_dps/HADOOP_consolidated_RT_v1x0_20120716_aa 
-rw-r--r-- 3 b_dps mdhi-technology 1073741824 2012-07-18 22:50 /apps/mdhi-technology/b_dps/HADOOP_consolidated_RT_v1x0_20120716_ab 

如何找到其中的這些包含字符串bcd4bc3e1380a56108f486a4fffbc8dc ?一旦我知道了,我可以手動編輯它們。

+0

Grep或Sed? 不是? – plast1K 2012-07-28 02:41:43

+0

問題在於,它不是UNIX文件系統,它是Hadoop文件系統,每當我嘗試像這樣的'bash-3。00 $ cd/apps/hdmi-technology/b_dps/real-time bash:cd:/ apps/hdmi-technology/b_dps/real-time:沒有這樣的文件或目錄我沒有這樣的文件或目錄。所以我需要一些其他方式來解決這個問題。 – ferhan 2012-07-28 02:50:51

回答

28

這是Hadoop的「文件系統」,而不是一個POSIX之一,所以試試這個:

hadoop fs -ls /apps/hdmi-technology/b_dps/real-time | awk '{print $8}' | \ 
while read f 
do 
    hadoop fs -cat $f | grep -q bcd4bc3e1380a56108f486a4fffbc8dc && echo $f 
done 

這應該工作,但它是串行的,因此可能會很慢。如果您的集羣可以帶走熱量,我們可以並行:

hadoop fs -ls /apps/hdmi-technology/b_dps/real-time | awk '{print $8}' | \ 
    xargs -n 1 -I^-P 10 bash -c \ 
    "hadoop fs -cat^| grep -q bcd4bc3e1380a56108f486a4fffbc8dc && echo ^" 

通知的-P 10選項xargs:這是多少個文件,我們將下載和並行搜索。從低開始增加數字,直到您使磁盤I/O或網絡帶寬達到飽和,無論您的配置如何。

編輯:鑑於你在SunOS(這是輕微腦死亡)試試這個:

hadoop fs -ls /apps/hdmi-technology/b_dps/real-time | awk '{print $8}' | while read f; do hadoop fs -cat $f | grep bcd4bc3e1380a56108f486a4fffbc8dc >/dev/null && echo $f; done 
+0

問題是,它不是一個UNIX文件系統,它是一個Hadoop文件系統,每當我嘗試像這樣''bash-3.00 $ cd/apps/hdmi-technology/b_dps/real-time bash:cd:/ apps/hdmi-technology/b_dps/real-time:沒有這樣的文件或目錄我沒有這樣的文件或目錄。 – ferhan 2012-07-28 02:50:23

+0

你認爲這個目錄存在嗎?你可以將它安裝到一個位置,然後cd進去嗎? – plast1K 2012-07-28 02:53:11

+0

我不知道我是否可以做到這一點,因爲該文件夾裏面有TB數據。順便說一句,我如何將它安裝到一個位置? – ferhan 2012-07-28 02:56:15

0

使用hadoop fs -cat(或更一般的hadoop fs -text)可能是可行的,如果你只是有兩個1 GB文件。對於100個文件,儘管我會使用streaming-api,因爲它可以用於adhoc查詢,而無需訴諸完整的mapreduce作業。例如。在你的情況下創建一個腳本get_filename_for_pattern.sh

#!/bin/bash 
grep -q $1 && echo $mapreduce_map_input_file 
cat >/dev/null # ignore the rest 

請注意,您必須閱讀整個輸入,爲了避免讓java.io.IOException: Stream closed例外。

然後發出命令

hadoop jar $HADOOP_HOME/hadoop-streaming.jar\ 
-Dstream.non.zero.exit.is.failure=false\ 
-files get_filename_for_pattern.sh\ 
-numReduceTasks 1\ 
-mapper "get_filename_for_pattern.sh bcd4bc3e1380a56108f486a4fffbc8dc"\ 
-reducer "uniq"\ 
-input /apps/hdmi-technology/b_dps/real-time/*\ 
-output /tmp/files_matching_bcd4bc3e1380a56108f486a4fffbc8dc 
hadoop fs -cat /tmp/files_matching_bcd4bc3e1380a56108f486a4fffbc8dc/* 

在新的發行mapred streaming,而不是hadoop jar $HADOOP_HOME/hadoop-streaming.jar應該工作。在後一種情況下,您必須正確設置您的$HADOOP_HOME才能找到jar(或直接提供完整路徑)。

對於更簡單的查詢,您甚至不需要腳本,但可以直接向-mapper參數提供命令。但是對於任何稍微複雜的事情,最好使用腳本,因爲逃避權利可能是一件苦差事。

如果您不需要縮小階段,請爲相應的-reduce選項(或僅使用-numReduceTasks 0)提供符號NONE參數。但在你的情況下,有一個減少階段是有用的,以便將輸出合併到一個文件中。