7

他人のコードをデバッグしていて、わざとコーディングしようとすると、どうすればよいか分からない状況に遭遇しました。これは、CentOS 6 ボックスで Bash 4.1.2 によって実行されている非常に大きな Bash スクリプトから来ています。プログラム全体は巨大ですが、次の関数で一貫してエラーが発生します。

get_las() {
    echo "Getting LAS..."
    pushd ${ferret_workdir} >& /dev/null
    #Download:
    if [ ! -e ${las_dist_file} ] || ((force_install)) ; then
        echo "Don't see LAS tar file ${las_dist_file}"
        echo "Downloading LAS from ${las_dist_file} -to-> $(pwd)/${las_dist_file}"

        echo "wget -O '${las_dist_file}' '${las_tar_url}'"
        wget -O "${las_dist_file}" "${las_tar_url}"
        [ $? != 0 ] && echo " ERROR: Could not download LAS:${las_dist_file}" && popd >/dev/null && checked_done 1
    fi
    popd >& /dev/null
    return 0
}

元の環境でスクリプトを最初から実行できるようにすると、このセクションに到達すると、次のエラーが発生して終了します。

Don't see LAS tar file las-esg-v7.3.9.tar.gz
Downloading LAS from las-esg-v7.3.9.tar.gz -to-> /usr/local/src/esgf/workbench/esg/ferret/7.3.9/las-esg-v7.3.9.tar.gz
wget -O 'las-esg-v7.3.9.tar.gz' 'ftp://ftp.pmel.noaa.gov/pub/las/las-esg-v7.3.9.tar.gz'
/usr/local/bin/esg-product-server: line 428: /usr/bin/wget: Argument list too long
 ERROR: Could not download LAS:las-esg-v7.3.9.tar.gz

引数が 2 つの小さな文字列だけであることを証明するために、デバッグ エコーも含まれていることに注意してください。

上記の時点でプログラムのエラーを発生させ、すぐに同じ期待スクリプトから再実行すると、唯一の変更点は、これより前のすべての段階が既に完了しており、それを検出してスキップしていることです。セクションはエラーなしで正常に実行されます。この動作は、私のテスト ボックスで 100% 再現可能です。コードを実行するすべてのトレースを消去すると、その後の最初の実行はこの時点で爆発し、その後の実行は問題ありません。

私が考えることができる唯一のことは、Bash 自体で何らかの形で MAX_ARG_PAGES メモリを目に見えない形でリークするような不明瞭なバグに遭遇したということですが、これを実現するための理論的な方法さえ考えられないので、私はここで尋ねます。

いったい何が起こっているのか、どうすれば停止させることができるでしょうか (カーネルを再コンパイルしてより多くのメモリを投入するなどの極端な手段は必要ありません)。

更新:コメントの質問に答えるには、428 行目は

wget -O "${las_dist_file}" "${las_tar_url}"
4

1 に答える 1

9

エラーE2BIGは、環境内のバイトとargvリストの合計を示しています。スクリプトは膨大な数(または膨大なサイズ)の変数をエクスポートしましたか?printenvの直前に実行wgetして、何が起こっているかを確認します。

于 2012-08-24T23:44:03.523 に答える