1

I have a Perl script that requires a couple of plugins, for istance nmap. How can I see if the plugins are already installed and, in case they are not, install them? I tryed with the following code but it doesn't work very well, what I am trying to do is capture the "bash: nmap: command not found" output. I tryed with both stdout and stderr.

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";
}
raz3r
  • 3,071
  • 8
  • 44
  • 66

3 Answers3

4

How can I see if the plugins are already installed and, in case they are not, install them?

This is not a good idea, do not check for dependencies at run time. Instead you declare the dependencies in your distro meta file and check for them at build time and perhaps abort the build. The easiest way to do so is with requires_external_bin from Module::Install. This integrates nicely into the existing RPM infrastructure. - In other words, learn the basics of packaging and which problems this solves.

If you cannot rely on the user having permission to install it system-wide, create an Alien distro that downloads the source and installs it into the share tree. But once you go down that rabbit hole, be aware that it's deep - you would also need to take care of the deps of nmap itself somehow.

Community
  • 1
  • 1
daxim
  • 39,270
  • 4
  • 65
  • 132
  • The purpose of all this is to create an installer for my Perl suite actually. Before installing additional plugins this "setup" installs Perl dependencies for instance. – raz3r Mar 22 '12 at 11:12
  • [Module::Install](http://p3rl.org/Module::Install) (or [Module::Build](http://p3rl.org/Module::Build) or [MakeMaker](http://p3rl.org/ExtUtils::MakeMaker)) is that installer. Why would you invent your own? – daxim Mar 22 '12 at 11:25
  • I am reading Module::Install documentation actually but my question is does this module require installation or is it a core one? My setup needs to run on machines that may not have anything. – raz3r Mar 22 '12 at 11:50
  • Module::Install is not a core module. It does not require prior installation on the target machine because a copy is bundled in the `inc` directory of the distribution. – daxim Mar 22 '12 at 12:54
0

What about this?

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";
}
user1126070
  • 5,059
  • 1
  • 16
  • 15
  • Can you explain the third line please? I don't like to use code that I don't understand :D – raz3r Mar 21 '12 at 09:12
  • This is the usually cruddy error checking for `system`. I would simply use [File::Which](http://p3rl.org/File::Which) instead, or if `system` cannot be avoided, at least [leave the error checking to IPC::System::Simple](http://stackoverflow.com/a/3478060). – daxim Mar 21 '12 at 11:44
  • $? contains the exit value of the command. The command executed in a shell so $? lower 128 bit contain the shell errors, upper 128 contain the actual script error. – user1126070 Mar 21 '12 at 11:45
  • the >> 8 shift binary, keep the upper part so the cmd exit value. Without this, if a cmd exit with 1 you will see 129 in $? – user1126070 Mar 21 '12 at 11:57
0

Like daxim pointed out requires_external_bin from Module::Install::External is a good way to ensure that your binary is installed.

If you can't use Module::Install in your application you might try searching the PATH environment variable like this:

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;
    }
}

This should output something like this:

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

The downside of this is of course, that the binary you are looking for has to reside in $PATH.

Sebastian Stumpf
  • 2,761
  • 1
  • 26
  • 34
  • A thoroughly debugged, portable incarnation of the path searching code above is available as [File::Which](http://p3rl.org/File::Which) from CPAN. – daxim Mar 22 '12 at 11:28