GNU/Linux >> Linux の 問題 >  >> Linux

Bash スクリプトのインスタンスが 1 つだけ実行されるようにする最善の方法は何ですか?

アドバイザリ ロックは古くから使用されており、bash スクリプトで使用できます。シンプルな flock が好き (util-linux[-ng] から) ) lockfile 以上 (procmail より) )。そして、終了時のトラップについて常に覚えておいてください (sigspec ==EXIT または 0 、これらのスクリプトでは、特定のシグナルをトラップすることは不要です)。

2009 年に、ロック可能なスクリプトのボイラープレートをリリースしました (当初は私の wiki ページで入手できましたが、現在は gist として入手できます)。これをユーザーごとに 1 つのインスタンスに変換するのは簡単です。これを使用すると、ロックや同期が必要な他のシナリオのスクリプトを簡単に作成することもできます。

便宜上、前述のボイラープレートを次に示します。

#!/bin/bash
# SPDX-License-Identifier: MIT

## Copyright (C) 2009 Przemyslaw Pawelczyk <[email protected]>
##
## This script is licensed under the terms of the MIT license.
## https://opensource.org/licenses/MIT
#
# Lockable script boilerplate

### HEADER ###

LOCKFILE="/var/lock/`basename $0`"
LOCKFD=99

# PRIVATE
_lock()             { flock -$1 $LOCKFD; }
_no_more_locking()  { _lock u; _lock xn && rm -f $LOCKFILE; }
_prepare_locking()  { eval "exec $LOCKFD>\"$LOCKFILE\""; trap _no_more_locking EXIT; }

# ON START
_prepare_locking

# PUBLIC
exlock_now()        { _lock xn; }  # obtain an exclusive lock immediately or fail
exlock()            { _lock x; }   # obtain an exclusive lock
shlock()            { _lock s; }   # obtain a shared lock
unlock()            { _lock u; }   # drop a lock

### BEGIN OF SCRIPT ###

# Simplest example is avoiding running multiple instances of script.
exlock_now || exit 1

# Remember! Lock file is removed when one of the scripts exits and it is
#           the only script holding the lock or lock is not acquired at all.

スクリプトがすべてのユーザーで同じである場合は、 lockfile を使用できます アプローチ。ロックを取得した場合は続行し、それ以外の場合はメッセージを表示して終了します。

例:

[Terminal #1] $ lockfile -r 0 /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] lockfile: Sorry, giving up on "/tmp/the.lock"

[Terminal #1] $ rm -f /tmp/the.lock
[Terminal #1] $ 

[Terminal #2] $ lockfile -r 0 /tmp/the.lock
[Terminal #2] $ 

/tmp/the.lock以降 取得されたスクリプトは、実行にアクセスできる唯一のスクリプトになります。完了したら、ロックを外すだけです。スクリプト形式では、これは次のようになります:

#!/bin/bash

lockfile -r 0 /tmp/the.lock || exit 1

# Do stuff here

rm -f /tmp/the.lock

flockだと思います おそらく最も簡単な (そして最も記憶に残る) バリアントです。 cron ジョブで使用して、DVD と CD を自動エンコードします

# try to run a command, but fail immediately if it's already running
flock -n /var/lock/myjob.lock   my_bash_command

-w を使用 タイムアウトの場合、またはロックが解除されるまで待機するオプションを除外します。最後に、man ページには複数のコマンドの良い例が示されています:

   (
     flock -n 9 || exit 1
     # ... commands executed under lock ...
   ) 9>/var/lock/mylockfile

Linux
  1. サービスがスクリプトで実行されているかどうかをテストする「適切な」方法は?

  2. Bashスクリプトのインスタンスを1つだけ実行するようにするにはどうすればよいですか?

  3. スクリプトが一定期間に1回実行されるようにするための最良の方法は?

  1. Ruby スクリプトのインスタンスが一度に 1 つだけ実行されるようにするにはどうすればよいですか?

  2. Bashでの$#の使用は何ですか

  3. Bashスクリプトの実行とソースの違いは何ですか?

  1. ソフトウェアがインストールされているかどうかを(スクリプトから)検出する最良の方法は?

  2. /bin を削除しました。回復する最良の方法は何ですか?

  3. .bashrc で環境変数を設定する最良の方法は何ですか?