複数のBashシェルスクリプトを並行して実行したい。ただし、競合状態は避けたいです。この目的に使用できるUnixコマンドは本当にアトミックで、どのように使用できますか?
複数のBashシェルスクリプトを並行して実行したい。ただし、競合状態は避けたいです。この目的に使用できるUnixコマンドは本当にアトミックで、どのように使用できますか?
回答:
lockfile
システムにインストールされていない場合はmkdir
、作業を実行します。これはアトミックな操作であり、ディレクトリが既に存在する場合は失敗します(-p
コマンドラインスイッチを追加しない限り)。
create_lock_or_wait () {
path="$1"
wait_time="${2:-10}"
while true; do
if mkdir "${path}.lock.d"; then
break;
fi
sleep $wait_time
done
}
remove_lock () {
path="$1"
rmdir "${path}.lock.d"
}
#!/bin/bash
# Makes sure we exit if flock fails.
set -e
(
# Wait for lock on /var/lock/.myscript.exclusivelock (fd 200) for 10 seconds
flock -x -w 10 200
# Do stuff
) 200>/var/lock/.myscript.exclusivelock
これにより、「(」と「)」の間のコードは一度に1つのプロセスでのみ実行され、プロセスはロックを長時間待機します。
lockf(1)
。
lockf(1)
ただし、この例で使用されている方法では機能しません。引数としてファイル記述子番号を取ることはできません。
lockfile(1)は良い候補のように見えますが、マシンにまだインストールされていない場合があるprocmailパッケージの一部であることに注意してください。これは十分に人気のあるパッケージであり、まだインストールされていない場合はシステムにパッケージ化する必要があります。私がチェックした4つのシステムのうち3つにはそれがあり、もう1つには使用可能です。
使い方は簡単です。
#!/bin/sh
LOCKFILE=$HOME/.myscript/lock
mkdir -p `dirname $LOCKFILE`
echo Waiting for lock $LOCKFILE...
if lockfile -1 -r15 $LOCKFILE
then
# Do protected stuff here
echo Doing protected stuff...
# Then, afterward, clean up so another instance of this script can run
rm -f $LOCKFILE
else
echo "Failed to acquire lock! lockfile(1) returned $?"
exit 1
fi
私が指定したオプションにより、1秒間に1回、最大15秒間再試行されます。永遠に待機する場合は、「-r」フラグを削除します。
Unixでのみ実行している場合は、fifoを使用します。作業記録をfifoに書き込み、このファイルからプロセスを読み取らせると、リーダーがfifoをブロックします。
ロックファイルは大丈夫ですが、あなたが説明するものにはfifoを使います
ここに投稿されているように:「シェルスクリプトの正しいロック?」、FLOM(Free LOck Manager)ツールを使用すると、コマンドとシェルスクリプトのシリアル化が実行と同じくらい簡単になります
flom -- command_to_serialize
ここで説明するように、FLOMでは、より洗練されたユースケース(分散ロック、リーダー/ライター、数値リソースなど)を実装できます:http ://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/
make(1)
が引き継ぐことを可能にする方法で依存関係を表現できませんか?(つまり、make -j 9
8つのコアがある場合は実行しますか?)これには、より細かい粒度で作業をインターリーブするという追加の利点があります。