2012-07-28 17 views
13

Sto lavorando con Hadoop e ho bisogno di trovare quale dei ~ 100 file nel mio filesystem Hadoop contengono una certa stringa.Grep su più file nel filesystem Hadoop

posso vedere i file che desidera cercare in questo modo:

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

..che torna più voci in questo modo:

-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 

Come posso trovare quale di questi contiene la stringa bcd4bc3e1380a56108f486a4fffbc8dc ? Una volta che lo so, posso modificarli manualmente.

+0

Grep or Sed? No? – plast1K

+0

Il problema con questo è, non è un file system UNIX, è un Hadoop File System, ogni volta che provo a fare questo 'bash-3.00 $ cd/apps/hdmi-technology/b_dps/real-time bash: cd:/apps/hdmi-technology/b_dps/real-time: nessun file o directory simile. Non ottengo alcun file o directory. Quindi ho bisogno di un altro modo per affrontare questo problema. – ferhan

risposta

28

Questo è un Hadoop "file system", non un POSIX uno, in modo da provare questo:

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 

Questo dovrebbe funzionare, ma è di serie e così potrebbe essere lenta. Se il cluster può prendere il calore, siamo in grado di parallelizzare:

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 ^" 

Avviso l'opzione -P 10-xargs: questo è il numero di file ci sarà scaricare e cercare in parallelo. Inizia basso e aumenta il numero fino a saturare l'I/O del disco o la larghezza di banda della rete, qualsiasi cosa sia rilevante nella tua configurazione.

EDIT: Dato che sei in SunOS (che è un po 'morte cerebrale) provare questo:

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

Problema con questo, non è un file system UNIX, è un Hadoop File System, ogni volta che provo a fare questo 'bash-3.00 $ cd/apps/hdmi-technology/b_dps/real-time bash: cd:/apps/hdmi-technology/b_dps/real-time: nessun file o directory simile non ottengo file o directory di questo tipo. – ferhan

+0

Sei sicuro che questa directory esista? Puoi montarlo in un posto e quindi inserirlo in esso? – plast1K

+0

Non sono sicuro di poterlo fare o meno dato che la cartella contiene TB di dati all'interno. A proposito, come posso montarlo in un luogo? – ferhan

0

Utilizzando hadoop fs -cat (o il più generico hadoop fs -text) potrebbe essere fattibile solo se si dispone di due 1 GB di file. Per 100 file, tuttavia, utilizzerei lo streaming-api perché può essere utilizzato per le query ad hoc senza ricorrere a un lavoro mapreduce completo. Per esempio. nel tuo caso creare uno script get_filename_for_pattern.sh:

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

Nota che si deve leggere l'intero di ingresso, al fine di evitare di ottenere java.io.IOException: Stream closed eccezioni.

quindi emettere i comandi

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/* 

In distribuzioni più recenti mapred streaming invece di hadoop jar $HADOOP_HOME/hadoop-streaming.jar dovrebbe funzionare. In quest'ultimo caso devi impostare correttamente il tuo $HADOOP_HOME per trovare il jar (o fornire direttamente il percorso completo).

Per query più semplici non è nemmeno necessario uno script, ma è sufficiente fornire direttamente il comando al parametro -mapper. Ma per qualcosa di leggermente complesso, è preferibile usare uno script, perché ottenere il diritto di fuga può essere un lavoro ingrato.

Se non è necessaria una fase di riduzione, fornire il parametro simbolico NONE all'opzione -reduce corrispondente (o utilizzare semplicemente -numReduceTasks 0). Ma nel tuo caso è utile avere una fase di riduzione per avere l'output consolidato in un singolo file.