如何从两个命令中创建一个linux shell命令,其行为类似于标准管道?

时间:2012-05-12 20:05:49

标签: python bash hadoop gzip hadoop-streaming

我正在尝试使用Hadoop Streaming来运行两个命令,例如gunzip | map_to_old_format.py,但是错误的是gzip说“| .gz not found”或者其他类似的东西(仅当通过Hadoop运行时...如果我在命令行上运行,它运行正常。)

由于我无法弄清楚如何在Python中使用gunzip,我想创建一个shell脚本来执行此命令组合(例如gunzip_and_map_to_old.sh)。我用以下方法尝试了这个,但gzip不喜欢(gzip抱怨“gzip:stdin:不是用gzip格式”):

#!/bin/bash
while read data; do
    echo $data | gunzip | map_to_old_format.py $2
done

关于python gunzip,我尝试了f = gzip.GzipFile("", "rb", fileobj=sys.stdin)以及描述为here的Wrapper方法。

3 个答案:

答案 0 :(得分:2)

我对Hadoop一无所知,但我猜测echo $data | gunzip不起作用,因为$data是一行data,而$data本身就是#!/bin/bash gunzip | map_to_old_format.py 可能不是gzip格式。而不是逐行传递数据,你不能只在bash脚本文件中执行此操作吗?

cat data.gz | gunzip_and_map_to_old.sh

然后您可以通过传递gzip文件来调用它:

{{1}}

答案 1 :(得分:1)

这不能回答我的确切问题,但我可以通过将-jobconf stream.recordreader.compression=gzip添加到我的Hadoop命令(source where I learned this)来绕过它:

hadoop jar /usr/lib/hadoop/contrib/streaming/hadoop-streaming-*.jar \
    -jobconf stream.recordreader.compression=gzip \
    -D mapred.reduce.tasks=0 \
    -file map_to_old_format.py \
    -mapper map_to_old_format.py \
    -input /mydata/* -output output/newdata

注意:我很好奇如何通过shell脚本来完成上述操作,所以如果有可能,请告诉我。

答案 2 :(得分:1)

Hadoop流通常使用TextInputFormat读取输入文件,并通过std in将其逐行传递给python映射器(使用制表符分隔键和值(在大多数情况下是行号和行文本)。 / p>

如果输入文件的文件扩展名没有以.gz结尾,那么hadoops TextInputFormat在向你传递一行之前不会知道gunzip文件内容。您可以按照其他答案中的建议配置属性以强制hadoop对该文件进行gunzip。