bashスクリプトでのマルチスレッド/フォーク


9

次の形式のbashスクリプトを作成しました。

#!/bin/bash
start=$(date +%s)
inFile="input.txt"
outFile="output.csv"

rm -f $inFile $outFile

while read line
do

    -- Block of Commands

done < "$inFile"

end=$(date +%s)

runtime=$((end-start))

echo "Program has finished execution in $runtime seconds."

whileループから読み込みます$inFile、ライン上でいくつかのアクティビティを実行して、結果をダンプ$outFile

以下のよう$inFile3500+ラインの長さで、スクリプトが完全に実行するための6-7時間かかります。この時間を最小限に抑えるために、このスクリプトではマルチスレッドまたはフォークを使用することを計画しています。8つの子プロセスを作成すると、からの8行$inFileが同時に処理されます。

これはどのように行うことができますか?


注意してください:異なるスクリプトは異なる出力ファイルに書き込む必要があります。また、記述されたスクリプトは、最初のアクションとして入力ファイルを削除します!
pjc50 2014

回答:


10

GNUparallelはまさにこの種のもののために作られています。一度に何回でもスクリプトを実行でき、入力ごとに異なるデータがパイプラインされます。

cat input.txt | parallel --pipe your-script.sh

デフォルトでは、システムのプロセッサ数に応じてプロセスを生成しますが、でカスタマイズできます-j N

特に巧妙なトリックは、シバンラッピング機能です。Bashスクリプトの最初の行を次のように変更した場合:

#!/usr/bin/parallel --shebang-wrap --pipe /bin/bash

標準入力でデータをフィードすると、すべて自動的に行われます。最後に実行する必要があるクリーンアップコードがある場合、これはあまり役に立ちません。

注意すべきことがいくつかあります。1つは、入力を連続したチャンクに分割し、一度に1つずつ使用することです。ラインをインターリーブしません。もう1つは、レコードの数に関係なく、それらのチャンクがサイズで分割されることです。を使用--block Nして、異なるブロックサイズをバイト単位で設定できます。あなたの場合、ファイルサイズの8分の1以下がほぼ適切です。それ以外の場合は、ファイルが1つのブロックにすべて収まるほど小さい可能性があるため、目的を達成できない可能性があります。

特定の異なるユースケースには多くのオプションがありますが、チュートリアルはかなりうまくカバーしています。興味のあるオプションには、--round-robinおよびがあり--groupます。


1
そのシバンラインをテストしましたか?複数の引数を持つシバンは移植できません。Linuxの場合#!a b cはになり["b c"]ますが、他の一部のシステムの場合はになり["b", "c"]ます。
nyuszika7h

1
この方法で使用すると、独自の引数を再解析します(そうでない場合、オプションはあまり使用されません)。
Michael Homer 2014

@MichaelHomer GNU parallelHTMLページのスクレイピングに使用する必要があります。このスレッドunix.stackexchange.com/questions/277609/…
確認いただけ
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.