Linux系のОSでバッチを起動する場合は、シェルを作成して、シェルからJavaなどのプログラムを呼び出すケースが多いかと思います。
バッチで問題になるのが「バッチの重複起動」になります。
“バッチ突き抜け”とも言いますが、1つのバッチが終了する前に同じバッチが起動してしまうと二重起動の状態になってしまい、思わぬ不具合が発生してしまいます。
この場合、プログラム側で重複起動をおこなわないような制御をおこなう必要があります。
今回は、このバッチ重複起動チェックをシェルだけで実現する方法を紹介します。
シェルだけで実現する方法なので非常にシンプルですが、確実に二重起動チェックを防ぐことができます。
環境情報
- OS:CentOS 7.6
pgrepコマンドとは
重複起動チェックで使用するコマンドは「pgrep」コマンドです。
「pgrep」コマンドは、プロセスが保持しているプロセス名属性からプロセスIDを取得するコマンドになります。
要は「pgrep」コマンドは、「ps」コマンドと「grep」を合体したコマンドですね。
psコマンドの出力結果をパイプ(|)で繋いでgrepで抽出することが多いかと思いますが、この操作を同時に実行することが「pgrep」コマンドになります。
基本的な文法は以下になります。
pgrep [オプション] [プロセスの特定パターン]
二重起動チェックのシェルプログラム
二重起動チェックのシェルプログラムは以下になります。
「pgrep」コマンドで自身のプロセス名のプロセス番号を取得し、そのプロセス番号と自身のプロセス番号と比較しています。
プロセス番号の比較結果が異なる場合は、自身のプロセスと同名の他プロセスが動作していると判断する、ということですね。
#!/bin/sh echo "start" PGREP=`pgrep -f $0 -o` PGREP_RSLT=$? if [ $$ != $PGREP ]; then echo "$0は起動中です。二重起動チェックです。" exit 1 fi sleep 180 echo "end"
上記サンプルプログラムを同時に実行すると、一方のシェルはチェックに掛かって起動できません。
二重起動チェックにかかりやすいように、180秒のスリープをおこないバッチ実行中の時間を長くとっています。
pgrepコマンドのオプションと特定パターン
二重起動チェックで使用している「pgrep」コマンドのオプションや、使用している特殊変数について説明していきます。
まずは「pgrep」コマンドのオプションです。
二重起動チェックで使用しているのは「-f」オプションと「-o」オプションになります。
「-f」「-o」オプション含めて、よく使用するオプションを紹介しておきます。
オプション | フルオプション | 説明 |
-f |
–full |
コマンドライン全体をパターンマッチの対象とする。 |
-o |
–oldest |
対象のプロセスから最も昔に起動されたものだけを対象とする。 |
-n |
–newest |
対象のプロセスから最も最近に起動されたものだけを対象とする。 |
-U ユーザ |
–uid ユーザ |
指定したユーザのプロセスを対象とする。「,」区切りで複数指定可能。 |
-v |
–inverse |
検索パターンの否定。 |
次に特殊変数についてです。
- $0:実行中プロセスのシェルファイル名。
- $?:直前に実行したコマンドの実行結果。成功時は「0」。失敗時は「0」以外。
- $$:実行中プロセスのプロセスID。
この特殊変数は非常に便利です。
実際の動きを紹介していきます。
$0特殊変数。実行中プロセスのファイル名。
実行中プロセスのシェルファイル名は「test.sh」となります。
そのファイル名がそのまま特殊変数として格納されています。
#!/bin/sh echo "start" echo $0 echo "end"
test.sh
$?特殊変数。コマンド実行結果。
コマンドの実行結果が格納されています。
厳密にはコマンドの実行結果を参照して、二重起動チェックに成功したか?失敗したか?についても処理分岐が必要となります。
#!/bin/sh echo "start" PGREP=`pgrep -f $0 -o` echo $? echo "end"
0
$$特殊変数。実行中プロセスのプロセスID。
実行中プロセスのプロセスIDが格納されています。
#!/bin/sh echo "start" echo $$ echo "end"
4269