如何使用 GNU parallel 在巨大的数据集上并行化包含嵌套 for 循环的 bash 脚本?
How to parallelize a bash script containing nested for loops on huge dataset with GNU parallel?
实际上,由于 OpenSSL,我启动了许多到 IP 地址的连接,以检测服务器是否接受指定的密码。我在 1 000 000 台服务器(包含在 "listeIpShuffle.txt" 中)上启动此脚本。因此,我的脚本包含 2 个 for 循环:第一个用于获取包含 IP 地址的文件的每一行,第二个用于测试服务器接受或拒绝时我的 OpenSSL 版本中可用的每个密码。
我在 GNU parallel 的文档上看到可以并行化这些循环:
*(for x in `cat xlist` ; do
for y in `cat ylist` ; do
do_something $x $y
done
done) | process_output*
...可以这样写:
*parallel do_something {1} {2} :::: xlist ylist | process_output*
但是我没有尝试在我的脚本中应用它...确实我包含我的 IP 地址的文件太大了,我得到了著名的 "Too many arguments" 错误...
我该如何处理这个问题并使我的脚本并行化?
提前致谢!
这是我的脚本:
#!/usr/bin/env bash
#on recupere toutes les ciphers d'openssl
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')
fichier="./serveursMail/listeIpShuffle.txt"
port=":25"
>resultDeprecatedCipher.txt
nbInconnu=0
echo Cipher list de $(openssl version).
for ligne in $(<$fichier)
do
ligneIp=$(echo $ligne | tr "|" "\n")
ip=($ligneIp)
ipPort=$ip$port
dns=$(echo $ligneIp |cut -f 2 -d ' ')
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')
for cipher in ${ciphers[@]}
do
if [[ $nbInconnu < 4 ]] ; then
echo -n Test $ligneIp " : " $cipher...
result=$(echo -n | timeout 10s openssl s_client -starttls smtp -cipher "$cipher" -connect $ipPort -servername $dns 2>&1) #pas de reponse apres dasn les 15sec => FAIL
if [[ "$result" =~ ":error:" ]] ; then
error=$(echo -n $result | cut -d':' -f6)
echo NON \($error\)
let "nbInconnu=0"
else
if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher :" ]] ; then
echo OUI
let "nbInconnu=0"
echo $ligneIp " : " $cipher >> resultDeprecatedCipher.txt
else
echo REPONSE INCONNUE
let "nbInconnu++" #incrementation
echo $nbInconnu
echo $result
fi
fi
else
let "nbInconnu=0"
break
fi
done
done
echo alt3.gmail-smtp-in.l.google.com > serverlist
echo fo-ds-ats.member.g02.yahoodns.net >> serverlist
doit() {
ip=""
port=""
cipher=""
openssl s_client -starttls smtp -cipher "$cipher" -connect $ip:$port -servername $ip < /dev/null
}
export -f doit
parallel --tag --timeout 10 --retries 4 doit :::: serverlist ::: 25 ::: $(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g') >tmp_results
# Post process tmp_results as needed
为了不让单个服务器过载,请添加 --shuf
。向 运行 尽可能多的并行添加 -j0
.
实际上,由于 OpenSSL,我启动了许多到 IP 地址的连接,以检测服务器是否接受指定的密码。我在 1 000 000 台服务器(包含在 "listeIpShuffle.txt" 中)上启动此脚本。因此,我的脚本包含 2 个 for 循环:第一个用于获取包含 IP 地址的文件的每一行,第二个用于测试服务器接受或拒绝时我的 OpenSSL 版本中可用的每个密码。
我在 GNU parallel 的文档上看到可以并行化这些循环:
*(for x in `cat xlist` ; do
for y in `cat ylist` ; do
do_something $x $y
done
done) | process_output*
...可以这样写:
*parallel do_something {1} {2} :::: xlist ylist | process_output*
但是我没有尝试在我的脚本中应用它...确实我包含我的 IP 地址的文件太大了,我得到了著名的 "Too many arguments" 错误... 我该如何处理这个问题并使我的脚本并行化?
提前致谢!
这是我的脚本:
#!/usr/bin/env bash
#on recupere toutes les ciphers d'openssl
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')
fichier="./serveursMail/listeIpShuffle.txt"
port=":25"
>resultDeprecatedCipher.txt
nbInconnu=0
echo Cipher list de $(openssl version).
for ligne in $(<$fichier)
do
ligneIp=$(echo $ligne | tr "|" "\n")
ip=($ligneIp)
ipPort=$ip$port
dns=$(echo $ligneIp |cut -f 2 -d ' ')
ciphers=$(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g')
for cipher in ${ciphers[@]}
do
if [[ $nbInconnu < 4 ]] ; then
echo -n Test $ligneIp " : " $cipher...
result=$(echo -n | timeout 10s openssl s_client -starttls smtp -cipher "$cipher" -connect $ipPort -servername $dns 2>&1) #pas de reponse apres dasn les 15sec => FAIL
if [[ "$result" =~ ":error:" ]] ; then
error=$(echo -n $result | cut -d':' -f6)
echo NON \($error\)
let "nbInconnu=0"
else
if [[ "$result" =~ "Cipher is ${cipher}" || "$result" =~ "Cipher :" ]] ; then
echo OUI
let "nbInconnu=0"
echo $ligneIp " : " $cipher >> resultDeprecatedCipher.txt
else
echo REPONSE INCONNUE
let "nbInconnu++" #incrementation
echo $nbInconnu
echo $result
fi
fi
else
let "nbInconnu=0"
break
fi
done
done
echo alt3.gmail-smtp-in.l.google.com > serverlist
echo fo-ds-ats.member.g02.yahoodns.net >> serverlist
doit() {
ip=""
port=""
cipher=""
openssl s_client -starttls smtp -cipher "$cipher" -connect $ip:$port -servername $ip < /dev/null
}
export -f doit
parallel --tag --timeout 10 --retries 4 doit :::: serverlist ::: 25 ::: $(openssl ciphers 'ALL:eNULL' | sed -e 's/:/ /g') >tmp_results
# Post process tmp_results as needed
为了不让单个服务器过载,请添加 --shuf
。向 运行 尽可能多的并行添加 -j0
.