1

我有很多具有通用配置的小型 Perl 守护进程。

目前,我使用它来加载设置:

在 myconfig.pm 中:

package MyConfig;
use base 'Exporter';

BEGIN {
    our @EXPORT = qw( $DB_DSN $DB_USER $DB_PWD );
}

our @EXPORT;
use vars @EXPORT;

$DB_DSN = "DBI:mysql:...";
$DB_USER = 'asdad';
...

在 daemon.pl 中:

use MyConfig;

这工作得很好。但是现在我有了新的要求,即在USR1收到信号时重新加载配置。我知道

$SIG{"USR1"} = sub { ... }

但接下来呢?use MyConfig再次?看起来很生气。

我的脚本必须在许多不同的平台和从 5.8 到现代的不同 perl 版本上运行,所以我试图避免使用 CPAN 模块。

请为我指出有关此任务的良好解决方案。

4

1 回答 1

2

当你时use Module (ARGS),这相当于

BEGIN {
  require Module;
  Module->import(ARGS);
}

require定位并编译模块。每个模块只发生一次。运行通常将 subs 和变量加载到调用者命名空间(由 Exporter 模块提供)的import特殊sub。import所以

$SIG{USR1} = sub { no warnings 'redefine'; MyConfig->import };

可能很好地解决您的问题。


跟进:

我编写了这个小程序来证明它是有效的(使用 ALRM 而不是 USR1):

use 5.010;
package Foo;
sub import{ # The Exporter module writes something similar.
  no strict 'refs';
  *{caller()."::var"} = \do{ my$x = 1 }; # put $foo into callers namespace
}

package main;
Foo->import(); # use Foo; if the package were in another file
$SIG{ALRM} = sub{ Foo->import; alarm 10 };
alarm 10;
while(1){
  say $var++;
  sleep 1;
}

输出:一次又一次地从 0 数到大约 10。请注意,我更改了循环内的变量,因此我可以看到它发生了变化并被正确重置。

于 2013-02-08T06:57:40.297 回答