adsperpage

世界で使われるオフィス互換ソフトウェア(無償)

2017年6月27日火曜日

【Linux CentOS 6.9 64bit】 同じパスで指定されるスクリプトが同時に実行されないようにする方法について


以下のようなテストスクリプトを作成した。
#ここから、#ここまで で示されるコードが、同時実行を防止する機能を持っている。
それ以外は、動作検証/デバッグ用である。

動作検証のため、sleep 70sを最後に置き、実行状態が70秒間、継続するようにした。

# cat /root/Python/webtest/com/test01.sh
#!/bin/sh

echo "PATH  is  $0"

echo "PPID is $PPID"
echo "PID is $$"

cmdline=`/bin/cat /proc/$$/cmdline`
echo "/proc/$$/cmdline  is  $cmdline"


#ここから、判定ルーチン

# コマンドラインで指定したパス名 $0 を検索キーにして、既に動作中のプロセスを検索し、最も古いプロセスのIDを取得する。 

psnum=`pgrep -fo "$0"`

# 取得した最古のプロセスIDと、自身のプロセスIDとを比較する。
# 一致しなければ、同一パス名 $0 で呼び出されたプロセスが他に既に存在しているため、二重起動を防止し中断する。
if [ "$$" != "$psnum"  ] ; then
        echo "no"     # 既に同じパスで指定されるスクリプトは起動中である。(二重起動防止のため中断)
        exit 1
fi

echo "ok"             #同じパスで指定されるスクリプトは起動していない。(さらに処理を継続)

#ここまで

echo "pgrep -fo $0  is  $psnum"

sleep 70s


cronでこのスクリプトが実行されるようにパスを指定して設定した。
# crontab -e
*/1     *       *       *       *       /root/Python/webtest/com/test01.sh

そして、cronによって実行されたスクリプトの結果を確認した。 
# tail /var/mail/root
PATH  is  /root/Python/webtest/com/test01.sh
PPID is 4166
PID is 4168
/proc/4168/cmdline  is  /bin/sh/root/Python/webtest/com/test01.sh
ok
pgrep -fo /root/Python/webtest/com/test01.sh  is  4168

このとき、まだ他で動作しているスクリプトはない。
このPIDは、4168 になった。
コマンドライン(/root/Python/webtest/com/test01.sh)をキーとしpgrepで取得したPIDは、4168 になった。
一致していることから、 /root/Python/webtest/com/test01.sh はただ一つしか動作していないことがわかった。(ok



sleep 70s が効いてプロセスが存在しているうちに、上記と同じパスでスクリプトを直接実行した。
# /root/Python/webtest/com/test01.sh
PATH  is  /root/Python/webtest/com/test01.sh
PPID is 4134
PID is 4174
/proc/4174/cmdline  is  /bin/sh/root/Python/webtest/com/test01.sh
no
pgrep -fo /root/Python/webtest/com/test01.sh  is  4168

このPIDは、4174 になった。
コマンドライン(/root/Python/webtest/com/test01.sh)をキーとしpgrepで取得したPIDは、4168(cronから実行されているスクリプトのPID) になった。

一致しないことから、 /root/Python/webtest/com/test01.sh は、別のプロセスとして動作中であることがわかった。(no



さらに、コマンドラインが別のものになるようにして、同じスクリプトを起動した。
# ./test01.sh
PATH  is  ./test01.sh
PPID is 4134
PID is 4469
/proc/4469/cmdline  is  /bin/sh./test01.sh
ok
pgrep -fo ./test01.sh  is  4469

この場合、既にcronで実行中のものとはパスが異なるのでプロセス検索で検出されない。
新規のプロセスとして実行できた。OKが表示された。
(しかし、当然、さらに同じパスで起動しようとすると、noが表示された。)



<参考>
・Linux - bash スクリプト二重起動チェック!
< http://www.mk-mode.com/octopress/2016/02/21/linux-bash-check-double-start/ > 2017年6月27日

・PGREP
< https://linuxjm.osdn.jp/html/procps/man1/pgrep.1.html > 2017年6月27日