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 进程只能运行一次,因为有一个锁信号量检查。但run1、run2、run3和run4可以同时运行。

现在我需要的是我想将进程数限制为最多四个。如果有人添加另一个 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)。

警告:如果您使用 cronfoo.pl作为多个不同用户运行,则必须仔细重新实现 setuid/权限更改代码。

进程间信号量,SysV

IPC::Semaphoresemget是 SysV系列函数的一个更方便的接口perlfunc,并且 SEM_UNDO 标志意味着您的某个工作人员的意外进程死亡不会“浪费”信号量增量。

警告:您可能需要在与 不同的单独进程中创建和初始化 SysV 信号量foo.pl,因为您无法在原子操作中创建和初始化 SysV 信号量。

进程间信号量,POSIXly

POSIX::RT::Semaphore还支持进程间信号量。该 API 比 SysV 更简单,并且可以专门创建信号量并将其初始化为原子系统调用中的值。

这可能是我会使用的。

于 2013-02-01T17:45:32.823 回答
0

请参阅上面@pilcrow 答案中@tsee 的评论。Steffen Muller 的IPC::ConcurrencyLimit可以很好地控制协同多处理的并发进程数。

于 2013-02-05T23:32:02.013 回答