我正在运行32核机器,我希望并行化一个非常简单的操作。 给定ip_addresses.txt文件,例如:
1.2.3.4
8.8.8.8
120.120.120.120
我想使用名为script.sh的脚本来解析这些IPS,该脚本将IP解析为各自的ISP。给出一个IP,并输出以下内容,例如给定1.2.3.4,这很好:
echo 1.2.3.4 | ./script.sh
1.2.3.4|Google
ip_addresses.txt包含数百万个唯一的IP,我正在考虑并行调用脚本。 所以我尝试了这个:
cat ip_addresses.txt | parallel ./script.sh
但没有输出。我希望有:
1.2.3.4|Google
120.120.120.120|Taiwan Academic Network
这样我就可以将它们重定向到一个文件。
我的脚本如下:
#!/bin/bash
while read ip
do
ret=$(/home/sco/twdir/product/trunk/ext/libmaxminddb-1.0.3/bin/mmdblookup --file /home/sco/twdir/product/trunk/ext/libmaxminddb-1.0.3/GeoIP2-ISP.mmdb --ip $ip isp 2>/dev/null | grep -v '^$' | grep -v '^ Could not find' | cut -d "\"" -f 2)
[[ $ret != "" ]] && echo -n "$ip|" && echo $ret;
done
我错过了什么?虽然我查了教程,但我无法解决这个问题。
答案 0 :(得分:1)
您的脚本从标准输入(STDIN)读取多行。 GNU Parallel默认将参数放在命令行上。要制作GNU Parallel,请在STDIN上输入--pipe。
cat ip_addresses.txt | parallel --pipe ./script.sh
这将为每个核心运行一个作业,并为每个作业传递1 MB的数据。但查找地址实际上不是CPU难,所以你可以为每个CPU运行10个作业(1000%):
cat ip_addresses.txt | parallel -j 1000% --pipe ./script.sh
这可能会达到您的文件句柄限制,因此:
cat ip_addresses.txt |\
parallel --pipe --block 50m --round-robin -j100 parallel --pipe -j50 ./script.sh
这将并行运行100 * 50 = 5000个作业。
如果您不希望在获得任何输出之前等待处理完整的1 MB,则可以将其降低到1k:
cat ip_addresses.txt | parallel -j 1000% --pipe --block-size 1k ./script.sh
cat ip_addresses.txt |\
parallel --pipe --block 50k --round-robin -j100 parallel --pipe --block 1k -j50 ./script.sh
答案 1 :(得分:0)
引用并行手册页。
对于每行输入,GNU parallel将以行作为参数执行命令。
输入中的每一行都是脚本的命令行参数,而不是标准输入。像这样:
./script.sh 1.2.3.4
你应该重写你的脚本,以便从变量$1
读取参数。
#!/bin/bash
ip=$1
ret=$(/home/sco/twdir/product/trunk/ext/libmaxminddb-1.0.3/bin/mmdblookup --file /home/sco/twdir/product/trunk/ext/libmaxminddb-1.0.3/GeoIP2-ISP.mmdb --ip $ip isp 2>/dev/null | grep -v '^$' | grep -v '^ Could not find' | cut -d "\"" -f 2)
[[ $ret != "" ]] && echo -n "$ip|" && echo $ret;
或者您可以使用并行的--pipe
选项。
$ cat ip_addresses.txt | parallel --pipe --block-size 10 ./script.sh