2

同時に複数回呼び出される可能性のあるbashスクリプトがあります。スクリプトがアクセスする(ファイルに保存されている)状態情報を保護するために、次の/tmpようなファイルロックを使用しています。

do_something()
{
...
}

// Check if there are any other instances of the script; if so exit
exec 8>$LOCK
if ! flock -n -x 8; then
        exit 1
fi

// script does something...
do_something

これで、このスクリプトの実行中に呼び出された他のインスタンスがすべて終了します。n回ではなく、n回の同時呼び出しがあった場合、スクリプトを1回だけ余分に実行したいのですが、次のようになります。

do_something()
{
...
}

// Check if there are any other instances of the script; if so exit
    exec 8>$LOCK
    if ! flock -n -x 8; then
        exit 1
    fi

// script does something...
do_something

// check if another instance was invoked, if so re-run do_something again
    if [ condition ]; then
       do_something
    fi

どうすればこれを行うことができますか?終了する前に群れの中のファイルに触れて、うまくいかない場合は、そのファイルを2番目の条件として使用します。

4

3 に答える 3

2

それらは誰もが好むものではありませんが、アトミックであるため、ロックファイルを作成するためのシンボリックリンクのファンでした。例えば:

lockfile=/var/run/`basename $0`.lock
if ! ln -s "pid=$$ when=`date '+%s'` status=$something" "$lockfile"; then
  echo "Can't set lock." >&2
  exit 1
fi

有用な情報をリンクターゲットに直接エンコードすることにより、ファイルへの書き込みによって生じる競合状態を排除します。

とは言うものの、Dennisが投稿したリンクは、スクリプトをさらに作成する前に理解しておく必要のある、はるかに有用な情報を提供します。上記の私の例は、BashFAQ / 045に関連しているようなもので、。を使用して同様のことを行うことを提案していmkdirます。

私があなたの質問を正しく理解していれば、2つのロックファイルを使用することで、あなたがやりたいことが(少し信頼性が低い)達成される可能性があります。最初のロックの設定に失敗した場合は、2番目のロックを試します。2番目のロックの設定に失敗した場合は、終了します。最初のロックをチェックした後、2番目の既存のロックをチェックする前に削除すると、エラーが発生します。このレベルのエラーが許容できるものであれば、それは素晴らしいことです。

これはテストされていません。しかし、それは私には合理的に見えます。

#!/usr/local/bin/bash

lockbase="/tmp/test.lock"

setlock() {
  if ln -s "pid=$$" "$lockbase".$1 2>/dev/null; then
    trap "rm \"$lockbase\".$1" 0 1 2 5 15
  else
    return 1
  fi
}

if setlock 1 || setlock 2; then
  echo "I'm in!"
  do_something_amazing
else
  echo "No lock - aborting."
fi
于 2012-06-05T05:20:37.797 に答える
2

物事を行う必要があることを知らせるフラグ(ロックファイル)を1つ用意し、常にそれを設定します。実行部分によって設定されていない別のフラグを用意します。

REQUEST_FILE=/tmp/please_do_something
LOCK_FILE=/tmp/doing_something

# request running
touch $REQUEST_FILE

# lock and run
if ln -s /proc/$$ $LOCK_FILE 2>/dev/null ; then
    while [ -e $REQUEST_FILE ]; do
        do_something
        rm $REQUEST_FILE
    done
    rm $LOCK_FILE
fi

スクリプト全体が実行されるたびに「do_something」が1回だけ実行されるようにする場合は、何らかのキューを作成する必要があります。全体的な構造は似ています。

于 2012-06-04T22:41:08.530 に答える
0

プロセス管理を参照してください。

于 2012-06-04T22:30:54.810 に答える