【问题标题】:How to see if a plugin is already installed with Perl如何查看是否已使用 Perl 安装插件
【发布时间】:2012-03-21 08:27:47
【问题描述】:

我有一个需要几个插件的 Perl 脚本,例如 nmap。如何查看插件是否已安装,如果没有,请安装它们?我尝试了以下代码,但效果不是很好,我想做的是捕获“bash:nmap:command not found”输出。我尝试了标准输出和标准错误。

print "Checking nmap...\n";

my ($stdout, $stderr) = capture {
    system("nmap");
};

if ($stdout=~m/command not found/) {
    print "nmap not found, installing...\n";
    system("rpm -i nmap-4.75-1.26.x86_64.rpm");
}

else {
    print "nmap is already installed.\n";
}

【问题讨论】:

    标签: perl plugins


    【解决方案1】:

    如何查看插件是否已安装,如果未安装,请安装它们?

    This is not a good idea,不在运行时检查依赖项。相反,您声明发行版元文件中的依赖项并在构建时检查它们,并可能中止构建。最简单的方法是使用requires_external_bin from Module::Install。这很好地集成到现有的 RPM 基础架构中。 - 换句话说,学习包装的基础知识以及这解决了哪些问题。

    如果您不能依赖有权在系统范围内安装它的用户,请创建一个 Alien 发行版,下载源代码并将其安装到共享树中。但是一旦你进入那个兔子洞,请注意它很深 - 你还需要以某种方式照顾deps of nmap itself

    【讨论】:

    • 这一切的目的实际上是为我的 Perl 套件创建一个安装程序。例如,在安装其他插件之前,此“设置”会安装 Perl 依赖项。
    • Module::Install(或Module::BuildMakeMaker)就是那个安装程序。为什么要自己发明?
    • 我实际上正在阅读 Module::Install 文档,但我的问题是这个模块需要安装还是核心模块?我的设置需要在可能没有任何东西的机器上运行。
    • Module::Install 不是核心模块。它不需要在目标机器上预先安装,因为副本捆绑在分发的inc 目录中。
    【解决方案2】:

    这个怎么样?

    my $cmd='which nmap';
    my $output = `$cmd 2>&1`;
    my $exit_value=$? >> 8;
    if ($exit_value){
      print "not found $cmd, error: $output\n";
    }else{
      print "Found $cmd at $output\n";
    }
    

    【讨论】:

    • 你能解释一下第三行吗?我不喜欢使用我不理解的代码:D
    • 这是对system 的常见错误检查。我会简单地改用File::Which,或者如果无法避免system,至少leave the error checking to IPC::System::Simple
    • $?包含命令的退出值。在 shell 中执行的命令 $?低 128 位包含 shell 错误,高 128 位包含实际脚本错误。
    • >> 8移位二进制,保留上半部分以便cmd退出值。如果没有这个,如果一个 cmd 退出 1 你会在 $? 中看到 129?
    【解决方案3】:

    就像 daxim 指出的那样,Module::Install::External 中的 requires_external_bin 是确保安装二进制文件的好方法。

    如果您不能在应用程序中使用 Module::Install,您可以尝试像这样搜索 PATH 环境变量:

    use File::Spec;
    
    $\="\n";
    print installed($_) ? "$_ installed" : "$_ not installed" for qw/nmap ls cat nosuchfile less/;
    
    sub installed {
        my $name = shift;
    
        foreach my $path (File::Spec->path()) {
            my $bin = File::Spec->catfile($path, $name);
            return $bin if -e -f -x $bin;
        }
    }
    

    这应该输出如下内容:

    $ perl test.pl
    nmap installed
    ls installed
    cat installed
    nosuchfile not installed
    less installed
    

    当然,这样做的缺点是,您要查找的二进制文件必须驻留在 $PATH 中。

    【讨论】:

    • 上述路径搜索代码的经过彻底调试的可移植化身可从 CPAN 以File::Which 的形式获得。
    猜你喜欢
    • 2016-11-30
    • 2013-03-24
    • 2020-01-08
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-06-15
    • 1970-01-01
    • 2022-10-17
    相关资源
    最近更新 更多