#バドシス 〜 日々のことを続く限り書いてみようと思って 〜

頑張って日々のことを書いていこうと思います。

【PHP】バッチの多重起動制御について

詳細! PHP 7+MySQL 入門ノート

バッチの多重起動の制御についてです。
色々方法はあるのでまとめようと思います。

多重制御の方法について

ロックファイルを作る

ポピュラーな方法みたいです。

バッチ起動時にロックファイルを作成し、実行完了したらロックファイルを削除する。

もし処理中にバッチが起動した場合、ロックファイルが存在するのでエラーにします。

 

しかしこの方法では、サーバーがダウンしたり、サーバーの再起動など、プログラムが強制終了したタイミングでロックファイルが残ってしまいます。

ロックファイルの制御について

ロックファイルの制御ですが、

  • ロックファイルのタイムスタンプを確認し、古いものは削除して実行する
  • ロックファイルにプロセスを残し、プロセスが一致しない場合は削除して実行する

 

などの選択があります。

qiita.com

アドバイザリロックでプロセスの多重起動を防止する

アドバイザリロックを簡単に説明すると、実行するプログラムファイルそのものをロックします。

こっちの方法ならロックファイルを作らなくても直接ファイル自体をロックして制御できるのでおススメです。

 

if ($this->checkLockFile() === false)
{
    print('既に起動されています。'.PHP_EOL);
 
    return;
}
 
$pid = getmypid();
echo "pid $pid\n";
echo "wait 10 sec ";

for ($i=0; $i<10; $i++)
{
    sleep(1);
    echo ".";
}

echo "\n";
exit;

 

/**
* Undocumented function
* @return void
*/
private function checkLockFile()
{
    static $fp;
    // ロックするファイル
    $fp = fopen(__FILE__, "r");

    // ファイルが有効かどうかチェック
    if (is_resource($fp) == false)
    {
        throw new \RuntimeException("unable open [" . __FILE__ . ']');
    }

    $wouldBlock = false;

    // ロックをかける
    // 「LOCK_EX」は排他ロック
    // 「LOCK_NB」を設定しないと、ロックが解除されるまで待つ
    if (flock($fp, LOCK_EX|LOCK_NB, $wouldBlock) == false)
    {
        // ロックがかかっている場合、falseを返す
        if ($wouldBlock)
        {
            return false;
        }

        throw new \RuntimeException("unable lock [" . __FILE__ . ']');
    }

    return true;
}

 

qiita.com

 

詳細! PHP 7+MySQL 入門ノート

詳細! PHP 7+MySQL 入門ノート