44

この記事は最終更新日から5年以上が経過しています。

投稿日

更新日

シェルスクリプトでの排他処理

業務系のシステムでシェルスクリプトを使用している場合など、 多重起動の防止などで排他制御が必要な場合が多々あると思いますが、その様な場合に役に立つシンボリックリンクを利用したシェルスクリプトでの排他制御方法です。

ただし、あくまでもシェルスクリプトによる処理ですので、厳密な意味での排他制御にはなり得ないために タイミングによってはどうしても多重起動してしまう危険性がある事は考慮しておく必要があります。

この処理では自分自身のプロセス ID をロックファイルとしてシンボリックリンクして利用しているので、排他制御を実施したプロセス ID が簡単に確認できる様にするとともに、何らかの理由で不正にロックファイルが残ってしまった場合にプロセス ID を確認する事で簡単にリカバリ可能としています。

なお、プロセス確認のために /proc を参照しているので、 Linux など /proc が存在するシステムのみで利用可能となっていますが、 ps (1) などを利用してプロセスを特定すれば /proc が無いシステムでも利用可能だと思います。
指摘によりプロセス確認の方法を汎用的な方法に変更しました。

sample
# ロックファイル
lockfile=${TMP:-/tmp}/${0##*/}

# 多重起動防止のために symbolic link を作成する
# link が作成できたら trap を設定し終了時に link を自動削除する
# synbolic link が存在しても /proc/${PID} がない場合は
# ロックファイルが不正に残っていると判断し削除して処理を続行する
while true
do
    if ln -s $$ ${lockfile} 2> /dev/null
    then
        # ロック取得できた
        break
    else
        # ロックファイルが既に存在している場合
        # ロックファイルから作成元の PID を取得する
        if [ kill -0 `ls -l ${lockfile} | sed 's!.* !!g'` > /dev/null 2>&1 ]
        then
            # プロセスが存在する場合
            echo "${0##*/}: exist another instance" 1>&2
            exit 1
        else
            # プロセスが存在しない場合はロックファイルを削除してリトライ
            rm -f ${lockfile}
        fi
    fi
done

# 終わる時は必ず lockfile を削除する
trap 'rm -f ${lockfile}; exit' 0 1 2 3 11 15

# 実際の処理
    :

新規登録して、もっと便利にQiitaを使ってみよう

  1. あなたにマッチした記事をお届けします
  2. 便利な情報をあとで効率的に読み返せます
ログインすると使える機能について
bsdhack
親バカがviでシェルスクリプトを書いてる様なヤツです。 古き良きUNIXが好きですが最近は Mac ばかり使ってます。 Unix/Linux 技術者をお捜しの方は是非声をかけて下さい

コメント

プロセスの存在チェックは kill -0 <PID> が定石で移植性もありです。

2

ありがとうございます。
そんな汎用的な方法があったんですね。

0
あなたもコメントしてみませんか :)
新規登録
すでにアカウントを持っている方はログイン
44