フォルダーのすべてのファイルをループして(通常は長時間続く)コマンドを実行する小さなスクリプトがあります。基本的には
for file in ./folder/*;
do
./bin/myProgram $file > ./done/$file
done
(構文エラーは無視してください。これは単なる擬似コードです)。
このスクリプトを同時に2回実行する必要がありました。 ./done/$fileが存在する場合は、明らかに実行は不要です。スクリプトを次のように変更しました
for file in ./folder/*;
do
[ -f ./done/$file ] || ./bin/myProgram $file >./done/$file
done
つまり、基本的に問題は、両方のスクリプト(または一般に複数のスクリプト)が実際に同じポイントにあり、失敗してコマンドが2回実行されるdone
ファイルの存在を確認することは可能ですか?
それは完璧だろうが、私はそれを非常に疑っている。これは簡単すぎるでしょう:D同じファイルを処理する可能性がある場合、スクリプトを何らかの方法で「同期」することは可能ですか?
これは可能であり、実際に発生します。この状況を回避するには、 ロックファイル を使用します。上記のページの例:
if mkdir /var/lock/mylock; then
echo "Locking succeeded" >&2
else
echo "Lock failed - exit" >&2
exit 1
fi
# ... program code ...
rmdir /var/lock/mylock
スクリプトの2つのインスタンスは確かにこのように相互作用する可能性があり、コマンドが2回実行されます。これは 競合状態 と呼ばれます。
この競合状態を回避する1つの方法は、各インスタンスが入力ファイルを別のディレクトリに移動して取得した場合です。 (同じファイルシステム内の)ファイルの移動は atomic です。入力ファイルの移動は望ましくない場合があり、これはすでに少し複雑になっています。
mkdir staging-$$ making-$$
for input in folder/*; do
name=${x#folder/}
staging=staging-$$/$name
output=making-$$/$name
destination=done/$name
if mv -- "$input" "$staging" 2>/dev/null; then
bin/myProgram "$staging" >"$output"
mv -- "$output" "$destination"
mv -- "$staging" "$input"
fi
done
広く利用可能なツールを使用してファイルを並列処理する簡単な方法は、 GNU make 、 -j
並列実行のフラグ 。このタスクのmakefileを次に示します(タブを使用してコマンドをインデントすることを忘れないでください)。
all: $(patsubst folder/%,done/%,$(wildcard folder/*))
done/%: folder/%
./bin/myProgram $< >[email protected]
mv [email protected] $@
実行make -j 3
3つのインスタンスを並行して実行します。
あなたが本当に複数のジョブを並行して実行しようとしていると感じています。ロックファイルは単に目的を達成するための手段にすぎません。
GNU Parallel http://www.gnu.org/software/parallel/ がインストールされている場合、これを行うことができます:
parallel ./bin/myProgram ::: ./folder/*
MyProgramを各コアで並行して実行します。
GNU Parallelは、次の方法で簡単にインストールできます。
wget http://git.savannah.gnu.org/cgit/parallel.git/plain/src/parallel
chmod 755 parallel
cp parallel sem
GNU Parallelの紹介動画をご覧ください:詳細は https://www.youtube.com/playlist?list=PL284C9FF2488BC6D1
ロックの問題は、中断できないロック(アトマと呼ばれることもある)を作成するメソッドが必要なことです。 Chrisが彼の回答で書いたように、mkdir
はそのような中断のない操作です(ファイルの作成はそのような操作ではありません)。
高レベルのコマンドもあります-通常はprocmail
パッケージに隠されています:lockfile
。このコマンドにはいくつかの素晴らしい機能があり、「ホイールを再発明」する必要なく、独自のスクリプトで簡単に使用できます(たとえば、ディレクトリの作成に基づいてロックする独自の関数を書く)。