如何使用 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.