例えば、1分毎に走らせてるバッチ処理があり、1分後にまだその処理が終わってない場合、同じ処理が重複して実行されてしまいます。これを避ける方法として、同じ処理が走ってるかどうかチェックする機能を実装しました。
バッチ処理の重複実行を回避するシェルスクリプト
シェルスクリプトがphpファイルを実行する例(このソースはgistでも管理しています。)
#!/bin/sh exec_file='/full/path/to/exec_file_name.php' pid=`pgrep -f $exec_file` #if not running if [ -z $pid ] ; then echo "Done!!" php $exec_file #don't exec else echo "canceled" fi
ポイントは、pgrepコマンドで、実行ファイル名を含んでいる処理のプロセスIDを取得していること。マッチしない場合は、空になるので、if内の条件が真になり実行されます。
また、文字列によるあいまい検索なので、実行ファイル名(exec_file)はフルパスを推奨します。
検証方法
動作の検証ですが、実行するphp内でsleep使って止めてみました。
<?php echo date('Ymd H:i:s')."\n"; //100秒とめます。1分以上(2分以内で)であればおけ。 sleep(100); ?>
これで、出力結果をファイルに吐き出すようにcronに設定して、
*/1 * * * * sh /path/to/test.sh 1>> /tmp/test.php.1.log
出力結果が以下のようになったので、OKかな。
・・・
Done!!
20110427 16:38:01
canceled
Done!!
20110427 16:40:01
canceled
Done!!
20110427 16:42:01
canceled
・・・
Done!!
20110427 16:38:01
canceled
Done!!
20110427 16:40:01
canceled
Done!!
20110427 16:42:01
canceled
・・・
Done!! とcanceledが交互に出力されてるのが分かります。