4

Perlスクリプトのコピーが一度に1つだけ実行されていることを確認する必要があります。ここでの提案によると、私はチェックを行うためにサブを書きました:

sub check_instances {
    open my $fh, '<', $0 or die $!; 

    unless (flock($fh, LOCK_EX|LOCK_NB)) {
        print "$0 is already running. Exiting.\n";
        exit 1;
    } 
}

しかし、それは機能しません。何が問題になる可能性がありますか?

4

4 に答える 4

5

サブ内でスコープされた字句ファイルハンドルを使用しています。戻るとcheck_instances、ファイルハンドルが自動的に閉じられ、ロックが解除されます。したがって、2つのコピーがまったく同時にチェックされない限り、競合が発生することはありません。

スクリプトが実行されている間(またはロックを維持したい限り)、ファイルハンドルが開いたままであることを確認してください。例えば:

{
my $fh;
sub check_instances {
    return if $fh; # We already checked
    open $fh, '<', $0 or die $!; 

    unless (flock($fh, LOCK_EX|LOCK_NB)) {
        print "$0 is already running. Exiting.\n";
        exit 1;
    } 
}
} # end scope of $fh

Perl 5.10が必要な場合は、これもstate変数を使用するのに適した場所です。

于 2010-10-19T08:31:47.477 に答える
2

他のインスタンスのプロセスリストを確認できますが(Proc :: ProcessTableが役立ちます)、多くの言語のUNIXプログラムで使用される一般的なルートはpidファイルを作成することです。File::Pidを参照してください。

于 2010-10-19T14:59:05.097 に答える
2

の通常のセマンティクスでflockは、ファイルハンドルを書き込みモードで開く必要がある場合があります。

open $fh, '>>', $0;
open $fh, '+<', $0;

(からperldoc -f flock

flock(3)のfcntl(2)エミュレーションでは、FILEHANDLEがLOCK_SHを使用するために読み取りインテントで開かれている必要があり、LOCK_EXを使用するために書き込みインテントで開かれている必要があることに注意してください。

于 2010-10-19T15:03:41.903 に答える
1

ファイルロックはさまざまな理由で失敗する可能性があります(たとえば、ファイルがNFSなどのネットワークファイルシステム上にある場合)。

私の解決策は、スクリプトの実行中にディレクトリを作成することです。ディレクトリの作成は常に不可分操作です。

于 2010-10-19T08:30:46.387 に答える