11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

flock(1)でシェルスクリプトの排他制御(Linux)

Last updated at Posted at 2013-08-07

シェルスクリプトで排他制御したいケースがたまにあります。

「多重起動の抑制」「二重起動の禁止」などとされることもあります。よくやるのは pid ファイルを作成したりロックファイルを作成したりだと思いますが、「ファイルの有無」とか「プロセスIDのチェック」がどうも不安定に感じていました。ファイルシステムの排他ロックとか簡単に使えればいいのに…!

調べてみると、flock(1) なんていう便利なものがあることがわかりました。

第二版

あえて、「singleton.sh を source することでスクリプトを排他制御する」という構成にこだわる。

singleton.sh
# 利用者はこのファイルを source します
_LOCK_FILE=$0.lock

exec {F_LOCK}>>$_LOCK_FILE

flock -w 1 ${F_LOCK}

if [ $? -ne 0 ]
then
	echo "maybe already running.">&2
	exit 1
fi

コメントでいただいた指摘通り、やはりロックファイルを作成して、終わったら消す方式では安定した排他制御は望めない。どうしても、「ロック解放」から「削除」までのタイムラグが発生してしまう。

しかたがないので、ロックファイルを置きっぱなしにすることにする。(悔しい)

利用側は以下のように。

app.sh
#!/bin/sh

source ./singleton.sh

echo "hogehoge"
sleep 2
echo "fugafuga"

自分自身をオープンしちゃう方法と問題点

たぶん自分自身をオープンしておくやり方の方がロックファイルより確実だと思います。

ただ、シェルスクリプトを実行する際、そのファイルが書き込み用にオープンされていると気持ち悪い感じで失敗します。

app2.sh
#!/bin/sh

exec {F_LOCK}>>$0

sleep 10
echo "ok"

こいつを平行して実行しようとすると、

[vagrant@localhost ~]$ ./app2.sh &
[2] 5762
[vagrant@localhost ~]$ -bash: ./app2.sh: /bin/sh: bad interpreter: テキストファイルがビジー状態です

こうなるのです。

一瞬これだけで排他制御できるじゃんと思いましたそううまい話でもなく、スクリプトを起動する瞬間しか排他効果がないので、exec によってオープンされるまでの間に素早く起動させれば余裕で平行実行可能です。

注意事項

  • 上のモジュール自体はネタです。
  • flockコマンドは Util-Linux のものです。Macでは動きませんし、古いバージョンのディストリビューションでも入ってません。
11
12
7

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
11
12

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?