4

我们维护了大量的 perl 模块,实际上它是如此之大,以至于我们甚至不知道我们负责的所有模块。我们想在某种日志中跟踪哪些脚本和模块访问了另一个模块,最好按模块名称存储,这样我们就可以评估更新模块是否存在风险,以便我们知道我们可能会影响什么。

有什么简单的方法可以做到这一点吗?

4

2 回答 2

3

你可以做一个简单的正则表达式搜索:

use strict;
use warnings;

my %modules;

foreach my $perl_file (@file_list) {

    open FILE, $perl_file or die "Can't open $perl_file ($!)";
    while (<FILE>) {

        if (/\s*(?:use|require)\s*([^;]+);/) {

            $modules{$1}{$perl_file}++;
        }
    }
}

这既快又脏,但它应该工作得很好。您最终会得到一个模块哈希,每个模块都指向使用它的文件的哈希。

当然,它会捕捉到类似use strict;但很容易忽略的东西。

如果你有类似的东西,use Module qw/function/;你会在分号之前抓住整个东西,但这应该没什么大不了的。您可以只搜索已知模块名称的键。

缺点是它不跟踪依赖关系。如果您需要该信息,您可以通过从 cpan 或其他方式获取它来添加它。

更新:如果你想在运行时记录这个,你可以创建一个包装器脚本,让你的perl命令指向你系统上的包装器。然后使包装器像这样:

use strict;
use warnings;

use Module::Loaded;

my $script = shift @ARGV;
#run program
do $script;

#is_loaded() gets the path of these modules if they are loaded.
print is_loaded('Some::Module');
print is_loaded('Another::Module');

但是,由于调用脚本的方法已经改变,您可能会冒着有趣的副作用的风险。这取决于你在做什么。

于 2012-10-25T09:04:05.283 回答
1

也许编辑 sitecustomize.pl 以便每次 Perl 运行时,它都会在日志中写入一些信息,然后对其进行分析?在 sitecustomize.pl 中添加类似这样的内容:

open (LOG, '>>',"absolutepathto/logfile.txt");
print LOG $0,"\t",$$,"\t",scalar(localtime),"\n";
open SELF, $0;
while (<SELF>) {
print LOG $_ if (/use|require/);
}
close SELF;
print LOG "_" x 80,"\n";
close LOG;

编辑:另外,我们忘记了 %INC 哈希,所以上面的代码可以重写如下,以包含更多关于哪些模块实际加载的数据 + 包含 do 函数所需的文件:

open (LOG, '>>',"absolutepathto/logfile.txt");
print LOG $0,' ',$$,' ',scalar(localtime),"\n";
open SELF, $0;
while (<SELF>) {
print LOG $_ if (/use|require/);
}
close SELF;
END {
local $" = "\n";
print LOG "Files loaded by use, eval, or do functions at the end of this program run:\n";
print LOG "@{[values %INC]}","\n";
print LOG "_" x 80,"\n";
close LOG;
}
于 2012-10-25T10:01:26.217 回答