セマフォ/ロックとして使用できるUnixコマンドは何ですか?


34

複数のBashシェルスクリプトを並行して実行したい。ただし、競合状態は避けたいです。この目的に使用できるUnixコマンドは本当にアトミックで、どのように使用できますか?


並列作業が必要なことは何ですか?並列make(1)が引き継ぐことを可能にする方法で依存関係を表現できませんか?(つまり、make -j 98つのコアがある場合は実行しますか?)これには、より細かい粒度で作業をインターリーブするという追加の利点があります。
フォンブランド

回答:


30

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"
}

26

flock(1)

#!/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つのプロセスでのみ実行され、プロセスはロックを長時間待機します。


良いもの、それについて知りませんでした。しかし、それは明らかにLinux固有の...だ
リッカルドMurri

1
@ Riccardo、FreeBSDには同様のコマンドがありますlockf(1)
アレックスB

lockf(1)ただし、この例で使用されている方法では機能しません。引数としてファイル記述子番号を取ることはできません。
チャーリー

11

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」フラグを削除します。



(マンページによると)「ファイルがロックされたら、少なくとも5分ごとにロックにタッチする必要があります。そうしないと、ロックが古くなったと見なされ、その後のロック試行が成功します。」
ジェイ

6

システムコールmkdir()はPOSIXファイルシステムではアトミックです。そのため、目的を達成するためmkdirに1回の呼び出しのみを含むような方法でコマンドを使用しmkdir()ます。(IOW、使用しないでくださいmkdir -p)。対応するロック解除はrmdirもちろんです。

mkdir()注意事項:ネットワークファイルシステムではアトミックではない場合があります。


あるrmdir原子したがって、また?
アレクセイマグラ

3

たぶん、lockfileコマンドが必要なことをするでしょう。

lockfile ~/.config/mylockfile.lock
.....
rm -f important.lock

これは間違ったファイルを削除するようです。
ベンジャミンW.

1

Unixでのみ実行している場合は、fifoを使用します。作業記録をfifoに書き込み、このファイルからプロセスを読み取らせると、リーダーがfifoをブロックします。

ロックファイルは大丈夫ですが、あなたが説明するものにはfifoを使います


1
fifoが競合状態を防ぐ方法について詳しく説明していただけますか?
G-Manは「Reinstate Monica」と言います14

0

ここに投稿されているように:「シェルスクリプトの正しいロック?」、FLOM(Free LOck Manager)ツールを使用すると、コマンドとシェルスクリプトのシリアル化が実行と同じくらい簡単になります

flom -- command_to_serialize

ここで説明するように、FLOMでは、より洗練されたユースケース(分散ロック、リーダー/ライター、数値リソースなど)を実装できます:http ://sourceforge.net/p/flom/wiki/FLOM%20by%20examples/

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.