为什么当环境改变Dev to Prod时,这个Unzip shell脚本的行为会有所不同?

问题描述 投票:1回答:1
output_path=s3://output
unziped_dir=s3://2019-01-03
files=`hadoop fs -ls $output_path/ | awk '{print $NF}' | grep .gz$ | tr '\n' ' '`;
for f in $files
do   
echo "available files are: $f"
filename=$(hadoop fs -ls $f | awk -F '/' '{print $NF}' | head -1)
hdfs dfs -cat $f | gzip -d | hdfs dfs -put - $unziped_dir"/"${filename%.*}
echo "unziped file names: ${filename%.*}"
done

输出:

开发:

available files are: s3://2019-01-03/File_2019-01-03.CSV.gz
unziped file names: File_2019-01-03.CSV
available files are: s3://2019-01-03/Data_2019-01-03.CSV.gz
unziped file names: Data_2019-01-03.CSV
available files are: s3://2019-01-03/Output_2019-01-03.CSV.gz
unziped file names: Output_2019-01-03.CSV

PROD:

available files are: s3://2019-01-03/File_2019-01-03.CSV.gz s3://2019-01-03/Data_2019-01-03.CSV.gz s3://2019-01-03/Output_2019-01-03.CSV.gz 
unziped file names: 

我试图查看目录并识别.gz文件并迭代它们以解压缩所有.gz文件并存储到不同的目录中。但是当我在EMR开发集群中运行此脚本时,它的工作正常。但是在生产集群中却没有。请查看上面脚本的行为。

shell apache-spark unix hadoop2
1个回答
1
投票

for f in $files中的单词分裂似乎存在问题。通常情况下,shell应该像在Dev上那样在空格处分割值$files。在开发f被设置为$files循环的每个循环中for的三个单词之一,在Prod f获得包括空格的$files的完整值。

你在某处设置变量IFS吗?

如果问题不在脚本的其他部分,您应该能够使用简化的脚本重现问题:

files="foo bar baz"
for f in $files
do   
  echo "available files are: $f"
done

如果此最小脚本没有显示差异,则问题出现在脚本的其他部分中。

要查看在Dev和Prod上IFS的值是否不同,您可以在for循环之前将其添加到最小脚本或原始脚本:

# To see if IFS is different. With the default value (space, tab, newline) the output should be
# 0000000   I   F   S   =   #      \t  \n   #  \n
# 0000012
echo "IFS=#${IFS}#" | od -c

如果你看到IFS值的差异,你必须找出IFS被修改的位置。

BTW:通常你可以在grep命令后省略| tr '\n' ' '。在处理\n时,shell应该接受for f in $files作为单词拆分字符。如果没有,这可能与您的问题的根源有关。

编辑:有一个更好的解决方案来逐行处理数据,请参阅 https://mywiki.wooledge.org/DontReadLinesWithForhttps://mywiki.wooledge.org/BashFAQ/001

你应该使用while read ...而不是for ...

修改后的脚本(未经测试)

output_path=s3://output
unziped_dir=s3://2019-01-03

hadoop fs -ls "$output_path"/ | awk '{print $NF}' | grep .gz$ | while IFS= read -r f
do   
    echo "available files are: $f"
    filename=$(hadoop fs -ls "$f" | awk -F '/' '{print $NF}' | head -1)
    hdfs dfs -cat "$f" | gzip -d | hdfs dfs -put - "${unziped_dir}/${filename%.*}"
    echo "unziped file names: ${filename%.*}"
done
© www.soinside.com 2019 - 2024. All rights reserved.