1

複数のディレクトリにシンボリックリンクされているプログラムがあります。

/main/foo.pl
/run1/foo.pl -> /main/foo.pl
/run2/foo.pl -> /main/foo.pl
/run3/foo.pl -> /main/foo.pl
/run4 /foo.pl -> /main/foo.pl

それらは cron ジョブとして実行されているため、crontab に次のエントリがあります。

*/2 * * * * /run1/foo.pl
*/2 * * * * /run2/foo.pl
*/2 * * * * /run3/foo.pl
*/2 * * * * /run4/foo .pl

foo.plのスニペットは次のとおりです。

use Fcntl qw(:flock);
use autodie qw(:all);
open my $self, '>', "$FindBin::Bin/lockme";
flock( $self, LOCK_EX|LOCK_NB )
    or die "Cannot acquire lock, already running!";

{
    my $long_proc = Process->new();
    $long_proc->run();
}        

ロック セマフォ チェックがあるため、各 cron プロセスは 1 回しか実行できないことがわかります。ただし、run1、run2、run3、および run4 は同時に実行できます。

ここで必要なのは、プロセスの数を最大 4 つに制限することです。誰かが次のような別の cron プロセスを追加した場合:

新しいシンボリックリンク:

/run5/foo.pl -> /main/foo.pl
/run6/foo.pl -> /main/foo.pl

追加の crontab:

*/5 * * * * /run5/foo.pl
* * * * * /run6/foo.pl

run1、run2、run3、および run4 がすべて実行中の場合は、常に run5 と run6 の両方をキューに入れる必要があります。したがって、常に 4 つのプロセスのみが実行されます。

どうすればそれを達成できますか?それを処理する CPAN モジュールはありますか?

ありがとう!

4

2 に答える 2

3

いくつかの一般的なアプローチがあります。

クイック アンド ダーティー

ディレクトリに N 個のロックファイルがあり、各プロセスが順番に各ファイルをロックしようとし、少しスリープします。

警告: これは忙しいループですが、それでも十分かもしれません。

デーモンの再設計

foo.plプロセスが子プロセスの同時実行を簡単に管理できるため、ローカル ソケット リスニング デーモンに変わります。cron ジョブをデーモンのブロック要求に変えて、何かをします。(たとえば、Parallel::ForkManagerを参照してください)。

foo.pl警告: cron を使用して複数の異なるユーザーとして実行していた場合は、setuid/privilege 変更コードを慎重に再実装する必要があります。

プロセス間セマフォ、SysV

IPC::Semaphoresemgetは、 の SysVファミリーの関数へのやや便利なインターフェイスですperlfunc。SEM_UNDO フラグは、ワーカーの 1 つの予期しないプロセス終了によってセマフォのインクリメントが「無駄」にならないことを意味します。

foo.pl警告:アトミック操作で SysV セマフォを作成および初期化することはできないため、おそらく とは別のプロセスで SysV セマフォを作成および初期化する必要があります。

プロセス間セマフォ、POSIXly

POSIX::RT::Semaphoreはプロセス間セマフォもサポートしています。API は SysV よりも単純で、セマフォを排他的に作成し、アトミック syscall の値に初期化できます。

これはおそらく私が使うものです。

于 2013-02-01T17:45:32.823 に答える
0

上記の@pilcrow回答の@tseeからのコメントを参照してください。SteffenMullerのIPC::ConcurrencyLimitは、協調マルチプロセッシングでの同時プロセスの数を適切に制御できます。

于 2013-02-05T23:32:02.013 に答える