Category: Linux System Administration
Author/Contact Info
Description: I have to keep updated a few RedHat 7.2 boxes, and wanted some simple automation to do it. I have a two liner bash script for wget-ting the updates from RH (and other sites) into the dirs 'rh/' and 'non_rh/' (I basically mirror RedHat updates for 7.2, plus a few packages, for local use).
The following Perl script then checks the local repository for RPMs, and compares the versions found with those on the boxes I maintain, using ssh connections (set up for requiring no password to the account I run this script on).
I'm sure it could be written better... so everybody's welcome to use it and improve it; and if you add something nice, add a comment and let other monks learn!
#!/usr/bin/perl
use strict;
use warnings;
use RPM qw(vercmp);

my $RPM_CMD=q(rpm -q --qf '%{NAME}:%{VERSION}:%{RELEASE}:%{ARCH}\n');
sub rpm{ my($n,$v,$r,$a)=@_[0..3]; return "$n-$v-$r.$a.rpm"; }

# use your local accounts here, I've left 
# only this one just to show the idea
my @accounts=(
 "root\@localhost",
);

#this is a complete hack, but a whole lot faster than using
#readdir and RPM:: over each file
my %updates=();
print "Checking for available updates... ";
chomp(
 my @vers=`ls rh/*.rpm non_rh/*.rpm|xargs $RPM_CMD -p`
);

# here we compute the split version numbers, 
# keeping track only of the most recent update
for(@vers){
 my($name,$version,$release,$arch)=split(':');
 if(
  !defined($updates{$name})||
  vercmp(($version,$release),@{$updates{$name}}[0..1])>0
 ){
  $updates{$name}=[$version, $release, $arch];
 }
}
print "done\n";

# let's dance, then: connect to servers, get the rpm's list
# and compare versions to find if there's something to be
# updated
for my $acct (@accounts){
 my ($user,$server)=split('@',$acct);
 print "Checking for installed packages on $server... ";
 #connect via a passwordless ssh account (authentication
 # is done via an ssh key previously set up)
 chomp(
  my @inst=`ssh -l $user $server "$RPM_CMD -a"`
 );
 print "done\n";
 print "######### updates for $server ############\n";
 my %new=();
 for(sort @inst){
  my ($name,$version,$release,$arch)=split(':');
  if($updates{$name}){
   my ($v,$r,$a)=@{$updates{$name}};
   if(vercmp(($version,$release),($v,$r))<0){
    print
     rpm($name,$v,$r,$a).
     " (updates ".rpm($name,$version,$release,$arch).")\n";
   }
  }
 } print "######### done with $server ############\n";
}