20MiBのCSVファイルのバッチを処理するスクリプトがあります。必要に応じてgzip圧縮して、約4MiBまで圧縮できます。何千ものファイルがあり、処理にはそれぞれ約30秒かかります。圧縮されていないファイルまたは圧縮されたファイルと解凍のいずれかを読むことは「ほぼ即時」であり、プロセスがプロセスレベルで並列化できることを強く示唆しています。確かに、それは複雑なRubyパイプラインを使って行われていることです。しかし、私はbashを使ってRubyコードを小さな部分に分割しようとしています。ジョブ制御のために、私はこのbashの機能バッシュプロセス置換バックグラウンドジョブコントロール
wait_until_job_available() {
maximum_jobs=${MAXIMUM_JOBS}
[ $# -eq 0 ] || maximum_jobs="${1}"
exit_status=0
RUNNING_JOBS=($(jobs -p))
while [ ${maximum_jobs} -le ${#RUNNING_JOBS[@]} ] && [ 0 -eq "${exit_status}" ]
do
# `wait -n` requires bash 4.3 which is unfortunately not available on several recent RHEL-based Linux distributions such as Oracle Linux
wait -n
exit_status=$?
RUNNING_JOBS=($(jobs -p))
done
return ${exit_status}
}
を思い付くだろうこれは私が上で利用可能なコアの数に(省略した場合、デフォルトは許可されたジョブを実行しているのオプションの最小数で、wait_until_job_available
を呼び出すことができますマシン)を起動し、bashパイプラインをバックグラウンド処理する。
だから私は、このようなように、それを使用することがあります:
while read file
do
CAT_COMMAND=cat
# if input file is gzip-compressed, pipe zcat instead of cat
if [ "${INFILE: -3}" == ".gz" ]
then
CAT_COMMAND=zcat
fi
# wait for a job to become available
wait_until_job_available
# read the uncompressed file, write processed data to file.out
process_file -i <(${CAT_COMMAND} ${file}) -o ${file}.out &
# while searching for filesystem paths of type _f_ile
done < <(find ${search_path} -type f)
# wait for all background jobs to finish
wait
あなたが見ることができるように、これはsearch_path
内のすべてのファイルを検索し、process_file
コマンドにそれを渡す必要があります。そうすることで、私はファイルをcatにするか、それ以外の場合はファイルを解凍するためにプロセス置換を使用します。入力ファイル名は圧縮されていないファイルの内容を出力するプロセスに置き換えられ、出力ファイルは ".out"が付加された元のファイル名になります。 process_file
の呼び出しはバックグラウンドになり、ジョブコントロールに送信されます。ダンディーに見えますよね?
一部のファイルが正しく処理されていないことに気づいた点を除いて。
process_file
で処理されると報告されたファイルは、process_file
の別々の同時インスタンスであっても、常に/dev/fd/63
と報告されています。一方、ファイルを一時的にコピーまたは解凍し、一時ファイルの名前をprocess_file
に渡すと、正常に実行され、すべてのファイルが正しく処理されているように見えます。
一時ファイルを作成することは避けたかったが、特にディスクに触れること(パフォーマンス)や、処理後に一時ファイルをクリーンアップ(削除)する必要があった。この問題を抱えていることはそれを妨げる。だから私は、代替プロセスパイプラインの疑似ファイル名に何らかの競合条件があるのではないかと不思議です。それとも、私が誤解しているようなプロセスの置き換えや仕事のコントロールについて何かありますか?
参考、私は のUbuntu Serverの14.04、Linuxの3.19.0-59 バッシュ4.3.11 のgzip 1.6
私の理解から、ファイル記述子はBashによって作成されていますが – inetknght