1. ホーム
  2. スクリプト・コラム
  3. パール

Perl で File::Lockfile を使用して、スクリプトの単一インスタンスを確保する

2022-02-02 09:20:47

私はPerlでいくつかの監視スクリプトを書き、crontabに置いて実行するようにしています。スクリプトの実行に時間がかかりすぎて、複数のインスタンスを同時に実行してしまうことがあるので、1つのインスタンスだけを実行するようにスクリプトに制御を加えることが必要です。

最もシンプルで自然なアイデアは、スクリプト内で空のロックファイルをチェックして作成し、スクリプトが終了したらそれを削除することです。これは、ファイルが存在するかどうかを判断することで、スクリプトが実行されたかどうかを判断する方法です。ただし、これにはバグがあり、実行中にスクリプトが異常終了し、ロックファイルが適切に削除されなかった場合、スクリプトは再び実行されなくなる。

空のロック・ファイルでうまくいかない場合は、ロック・ファイルにプロセスのPID番号などの内容を少し追加し、そのPID番号のプロセスがまだ実行されているかどうかをチェックすることで、上記のバグを回避することを検討してみてください。CPAN には File::Lockfile, File::Pid, Proc::PID::File など、これを実現する既成のモジュールがたくさんあります。

非常にシンプルなFile::Lockfileの例です。

以下はそのコード・スニペットです。

コピーコード コードは以下の通りです。

#! /usr/bin/perl -w
useFile::Lockfile;
# lockfile is located in the /tmp directory and is called test_file_lock.lck
my $lockfile= File::Lockfile->new('test_file_lock','/tmp');
# Check if the script is already running, and exit if it is
if ( my $pid= $lockfile->check ) {
  print"program is already running with PID: $pid";
  exit;
}
#Update the lock file
$lockfile->write;
# Script logic
sleep30
#deletelockfile
$lockfile->remove;

File/Lockfile.pm のソースコードを見てみると、ロックファイルに記録されているプロセスが既に実行されているかどうかの判断は kill -0 $pid で簡単にできることがわかると思います。つまり、上記のモジュールが無くても、自分で実装するのはとても簡単なのです。

概要を説明します。

この方法は、単一インスタンスを制限するスクリプトでよく使用され、MySQL などのプログラムも、各起動前に最後のレガシー mysql.pid ファイルをチェックします。

もう一つの方法。ロックファイルに排他ロックをかけ、一意性を確保するためにロックがあるかどうかを判断する。