Scripting

純 Perl RPM 版本檢查器

  • September 16, 2016

我有一台機器位於無法訪問網際網路的安全環境中。我有一個 CentOS 的基本負載和一些額外的 RPM。這包括基本的 PERL 安裝,沒有額外的模組。它也沒有安裝 GCC,所以我不能手動安裝新模組,也不能使用 CPAN 安裝它們。因此,我需要一個純粹的 Perl 解決方案。

我被要求創建一個 Perl 腳本,該腳本將驗證機器是否安裝了特定的 RPM 列表,並且它們是特定版本或更高版本。

這是我到目前為止所擁有的:

#!/usr/bin/perl

use strict;
use warnings;

# This is the list of RPMs to look for on the machine.
my @RPMs = ("bwm-ng",
       "celt051",
       "device-mapper-multipath",
       "device-mapper-multipath-libs",
       "dhcp",
       "dhcp-common",
       "ebtables",
       "freeglut",
       "glusterfs-api",
       "glusterfs-libs",
       "gnutls-utils",
       "gpm",
       "hmaccalc",
       "iftop",
       "iperf",
       "ipsec-tools",
       "iptraf",
       "iscsi-initiator-utils",
       "libsysfs",
       "lm_sensors",
       "lm_sensors-libs",
       "log4cpp",
       "lrzsz",
       "lzop",
       "mcsctrans",
       "minicom",
       "nc",
       "netcf-libs",
       "net-snmp",
       "net-snmp-libs",
       "net-snmp-utils",
       "omping",
       "perl-AppConfig",
       "perl-Pod-POM",
       "perl-Template-Toolkit",
       "pimd",
       "python-lxml",
       "quagga",
       "radvd",
       "smcroute",
       "usbredir",
       "yajl");

# These are the RPM versions that they should be equal to or newer than.
my @RPMVersions = ("bwm-ng-0.6-6.el6.2.x86_64",
       "celt051-0.5.1.3-0.el6.x86_64",
       "device-mapper-multipath-0.4.9-87.el6.x86_64",
       "device-mapper-multipath-libs-0.4.9-87.el6.x86_64",
       "dhcp-4.1.1-49.P1.el6.centos.x86_64",
       "dhcp-common-4.1.1-49.P1.el6.centos.x86_64",
       "ebtables-2.0.9-6.el6.x86_64",
       "freeglut-2.6.0-1.el6.x86_64",
       "glusterfs-api-3.4.0.57rhs-1.el6_5.x86_64",
       "glusterfs-libs-3.4.0.57rhs-1.el6_5.x86_64",
       "gnutls-utils-2.8.5-18.el6.x86_64",
       "gpm-1.20.6-12.el6.x86_64",
       "hmaccalc-0.9.12-2.el6.x86_64",
       "iftop-1.0-0.7.pre4.el6.x86_64",
       "iperf-2.0.5-11.el6.x86_64",
       "ipsec-tools-0.8.0-25.3.x86_64",
       "iptraf-3.0.1-14.el6.x86_64",
       "iscsi-initiator-utils-6.2.0.873-14.el6.x86_64",
       "libsysfs-2.1.0-7.el6.x86_64",
       "lm_sensors-3.1.1-17.el6.x86_64",
       "lm_sensors-libs-3.1.1-17.el6.x86_64",
       "log4cpp-1.0-13.el6_5.1.x86_64",
       "lrzsz-0.12.20-27.1.el6.x86_64",
       "lzop-1.02-0.9.rc1.el6.x86_64",
       "mcsctrans-0.3.1-4.el6.x86_64",
       "minicom-2.3-6.1.el6.x86_64",
       "nc-1.84-24.el6.x86_64",
       "netcf-libs-0.2.4-3.el6.x86_64",
       "net-snmp-5.5-54.el6.x86_64",
       "net-snmp-libs-5.5-54.el6.x86_64",
       "net-snmp-utils-5.5-54.el6.x86_64",
       "omping-0.0.4-1.el6.x86_64",
       "perl-AppConfig-1.66-6.el6.x86_64",
       "perl-Pod-POM-0.25-2.el6.x86_64",
       "perl-Template-Toolkit-2.22-5.el6.x86_64",
       "pimd-2.3.0-1.x86_64",
       "python-lxml-2.2.3-1.1.el6.x86_64",
       "quagga-0.99.23.1-2014082501.x86_64",
       "radvd-1.6-1.el6.x86_64",
       "smcroute-2.0.0-0.x86_64",
       "usbredir-0.5.1-2.el6.x86_64",
       "yajl-1.0.7-3.el6.x86_64");

my $RPMname; #This reprepsents an individual RPM name within the @RPMs array.

foreach $RPMname (@RPMs){ # Loop through the @RPMs array and query the RPM database for each RPM.
   my $cmd = "rpm -qa | grep " . $RPMname;

   my @cmdResults = `$cmd`;

   if (! @cmdResults){
       print "\tMissing RPM: " . $RPMname . "\n\n"; # If the RPM isn't installed; inform the user.
   } else {
       foreach(@cmdResults){
           print "\t" . $_ . "\n"; # Print the version of the RPM that's currently installed.

           # Compare the RPM version that's installed with the corresponding version that should be installed
           # as listed in the @RPMVersions array.
           # write some magic here. <------

       }
   }
}

exit(0);

我發現似乎是一個可能的解決方案,但我似乎無法弄清楚如何調整適合我的場景的程式碼。

見這裡:http ://www.perlmonks.org/bare/?node=240384

由於我上面提到的限制,我不能使用 RPM::VersionSort 或其他幾個與 RPM 相關的模組。

任何幫助將不勝感激。

謝謝!

一些提示

你不需要 grep 例如

rpm -q radvd
radvd-1.9.2-9.el7.x86_64
echo $?
0

如果包裹缺少 $? 是 1

rpm -q nc 
package nc is not installed
echo $?
1

您可以使用 –queryformat 獲取已安裝 rpm 包的版本

rpm -q radvd --queryformat "%{VERSION}\n"
1.9.2

僅使用 rpm 即可完成更多工作 -請查看 rpm.org 站點

您甚至可以在不使用 perl 的情況下逃脫,因此請在 SO 上查看 Dennis 的答案。

雖然這不能回答我最初的問題,但我想提供我最終得到的結果。我已經能夠說服當權者允許我安裝 RPM::VersionSort Perl 模組。所以這不是我希望找到的純 Perl 解決方案。

這是我現在為任何感興趣的人使用的內容:

#!/usr/bin/perl

use strict;
use warnings;
use RPM::VersionSort;

my $cmd;
my $cmdResults;
my %installedRPMs; #This will hold a list of all the RPMs from the baseRPMs list that ARE currently installed on the machine.
my @missingRPMs; #This will hold a list of all the RPMs from the baseRPMs list that ARE NOT installed on the system.
my %baseRPMs; #This is the list of RPMs that should be installed on the system and their corresponding version numbers.

%baseRPMs = ("bwm-ng" => "0.6-6.el6.2",
       "celt051" => "0.5.1.3-0.el6",
       "device-mapper-multipath" => "0.4.9-87.el6",
       "device-mapper-multipath-libs" => "0.4.9-87.el6",
       "dhcp" => "4.1.1-49.P1.el6.centos",
       "dhcp-common" => "4.1.1-49.P1.el6.centos", 
       "ebtables" => "2.0.9-6.el6",
       "freeglut" => "2.6.0-1.el6",
       "glusterfs-api" => "3.4.0.57rhs-1.el6_5",
       "glusterfs-libs" => "3.4.0.57rhs-1.el6_5",
       "gnutls-utils" => "3.8.5-18.el6",
       "gpm" => "1.20.6-12.el6",
       "hmaccalc" => "0.9.12-2.el6",
       "iftop" => "1.0-0.7.pre4.el6",
       "iperf" => "2.0.5-11.el6",
       "ipsec-tools" => "0.8.0-25.3",
       "iptraf" => "3.0.1-14.el6",
       "iscsi-initiator-utils" => "6.2.0.873-14.el6",
       "libsysfs" => "2.1.0-7.el6",
       "lm_sensors" => "3.1.1-17.el6",
       "lm_sensors-libs" => "3.1.1-17.el6",
       "log4cpp" => "1.0-13.el6_5.1",
       "lrzsz" => "0.12.20-27.1.el6",
       "lzop" => "1.02-0.9.rc1.el6",
       "mcsctrans" => "0.3.1-4.el6",
       "minicom" => "2.3-6.1.el6",
       "nc" => "1.84-24.el6",
       "netcf-libs" => "0.2.4-3.el6",
       "net-snmp" => "5.5-54.el6",
       "net-snmp-libs" => "5.5-54.el6",
       "net-snmp-utils" => "5.5-54.el6",
       "omping" => "0.0.4-1.el6",
       "perl-AppConfig" => "1.66-6.el6",
       "perl-Pod-POM" => "0.25-2.el6",
       "perl-Template-Toolkit" => "2.22-5.el6",
       "pimd" => "2.3.0-1",
       "python-lxml" => "2.2.3-1.1.el6",
       "quagga" => "0.99.23.1-2014082501",
       "radvd" => "1.6-1.el6",
       "smcroute" => "2.0.0-0",
       "usbredir" => "0.5.1-2.el6",
       "yajl" => "1.0.7-3.el6",
   );

print "The following RPMs and version numbers will be checked against this system:\n";
foreach(keys %baseRPMs){
   print "\t" . $_ . ": " . %baseRPMs($_) . "\n";
}

print "Press any key to continue.";
<STDIN>;

#Loop through the %baseRPMs list and build both the %installedRPMs list as well as the @missingRPMs list.
for my $pkg (keys %baseRPMs){
   $cmd = "rpm -q " . $pkg . " --queryformat \"%{VERSION}-%{RELEASE}\"";
   $cmdResults = `$cmd`;
   if ($cmdResults =~ /not installed/) {
       push @missingRPMs, $pkg;
   } else {
       $installedRPMs{$pkg} = $cmdResults;
   }
}

#Loop through the %installedRPMs list and verify their version numbers against the %baseRPMs list.
foreach (keys %installedRPMs){
   if (exists $baseRPMs{$_}){
       print "Expected: " . $_ . ": " . $baseRPMs{$_} .  "\n";
       print "Installed: " . $_ . ": " . $installedRPMs{$_} .  "\n";
       if (rpmvercmp($installedRPMs{$_}, $baseRPMs{$_}) < 0 ) {
           print "RESULT: !!FAIL!! " . $_ . " version is OLDER than the specified version in the Functional Test Plan.\n";
       } else {
           print "RESULT: PASS. " . $_ . " version is equal to or newer than the specified version in the Functional Test Plan. \n";
       }
       print "-----------------------------------------------------------------------------------------------------\n\n";
   }
}

#Print the list of @missingRPMs.
if (@missingRPMs){
   print "The following RPMs are NOT installed as defined by the Functional Test Plan:\n";
   foreach(@missingRPMs){
       print "\t" . $_ . "\n";
   }
   print "\n*Any missing RPMs indicates the system is NOT built as defined by the Functional Test Plan.*\n";
}

print "\n";

exit(0)

;

引用自:https://serverfault.com/questions/802165