web-dev-qa-db-fra.com

Grep sur plusieurs fichiers dans le système de fichiers Hadoop

Je travaille avec Hadoop et je dois trouver lequel des ~ 100 fichiers de mon système de fichiers Hadoop contient une certaine chaîne.

Je peux voir les fichiers que je souhaite rechercher comme ceci:

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

..qui retourne plusieurs entrées comme ceci:

-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

Comment trouver lequel de ces noms contient la chaîne bcd4bc3e1380a56108f486a4fffbc8dc? Une fois que je sais, je peux les éditer manuellement.

16
arsenal

Ceci est un "système de fichiers" hadoop, pas un POSIX, alors essayez ceci:

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

Cela devrait fonctionner, mais il est en série et peut donc être lent. Si votre cluster peut supporter la chaleur, nous pouvons paralléliser:

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

Remarquez l'option -P 10 à xargs: c'est le nombre de fichiers que nous allons télécharger et rechercher en parallèle. Commencez bas et augmentez le nombre jusqu'à saturer les E/S du disque ou la bande passante réseau, quelle que soit la pertinence de votre configuration.

EDIT: Étant donné que vous utilisez SunOS (qui est un peu mort cérébrale), essayez ceci:

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
29
phs

Vous souhaitez appliquer la commande grep sur un dossier hdfs

hdfs dfs -cat /user/coupons/input/201807160000/* | grep -c null

ici, le chat passe récursivement dans tous les fichiers du dossier et j'ai appliqué grep pour trouver le nombre.

0
Mukesh Gupta

Utiliser hadoop fs -cat (ou le plus générique hadoop fs -text) pourrait être réalisable si vous ne disposez que de deux fichiers de 1 Go. Pour 100 fichiers, je voudrais utiliser le streaming-api car il peut être utilisé pour des requêtes ad hoc sans recourir à un travail de mapreduce à part entière. Par exemple. dans votre cas, créez un script get_filename_for_pattern.sh:

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

Notez que vous devez lire la totalité de l'entrée pour éviter les exceptions Java.io.IOException: Stream closed.

Puis lancez les commandes

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

Dans les distributions plus récentes, mapred streaming au lieu de hadoop jar $HADOOP_HOME/hadoop-streaming.jar devrait fonctionner. Dans ce dernier cas, vous devez définir votre $HADOOP_HOME correctement afin de trouver le fichier jar (ou fournir directement le chemin complet).

Pour des requêtes plus simples, vous n'avez même pas besoin d'un script, vous pouvez simplement fournir directement la commande au paramètre -mapper. Mais pour tout ce qui est un peu complexe, il est préférable d’utiliser un script, car bien s’échapper peut être une corvée.

Si vous n'avez pas besoin d'une phase de réduction, indiquez le paramètre NONE symbolique dans l'option -reduce correspondante (ou utilisez simplement -numReduceTasks 0). Mais dans votre cas, il est utile d’avoir une phase de réduction afin que la sortie soit consolidée dans un fichier unique.

0
David Ongaro