#!/usr/local/bin/perl -w # $Id$ # $Source$ use strict; use Getopt::Std; use RPM::Perlonly; use Data::Dumper; my @RPMPATHS=( "/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/7.3/en/os/i386/RedHat/RPMS", "/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/updates/7.3/en/os/i386", "/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/updates/7.3/en/os/i686", "/home/ward/REDHAT73/ftp.nluug.nl/pub/os/Linux/distr/RedHat/ftp/pub/redhat/linux/updates/7.3/en/os/noarch", "/home/ward/REDHAT73/homemade", ); my %instrpms = (); my %refrpms = (); my %option = (); &cmdline; # Met pathread en RPM-Perlonly-1.0.1 moet het mogelijk zijn te bepalen # welke RPM de nieuwste is. Hierna is het (denk ik) relatief eenvoudig # te bepalen op welke systemen er dus packages geupdate moeten worden... sub pathread { my %entry = (); my ( $line, $prefix ); foreach $prefix ( @RPMPATHS ) { opendir DH, $prefix; while ($line = readdir DH) { if ($line =~ /\.rpm$/ ) { # &splitname($line); tie my %rpm, "RPM::Perlonly", "$prefix/$line" or die "Problem, could not open $line: $!"; #foreach ( sort keys %rpm ) { # print "$_ -> $rpm{$_}\n"; #} #print "Fullname $line\n"; #print " NAME: $rpm{'NAME'}\n"; #print " VERSION: $rpm{'VERSION'}\n"; #print " RELEASE: $rpm{'RELEASE'}\n"; if ( ! exists( $rpm{'EPOCH'} ) ) { $rpm{'EPOCH'} = 0; } #print " ARCH: $rpm{'ARCH'}\n"; push @{$refrpms{$rpm{'NAME'}}}, ( { 'NAME', $rpm{'NAME'}, 'BUILDTIME', $rpm{'BUILDTIME'}, 'VERSION', $rpm{'VERSION'}, 'RELEASE', $rpm{'RELEASE'}, 'EPOCH', $rpm{'EPOCH'}, 'ARCH', $rpm{'ARCH'}, 'FILENAME', $line } ); untie(%rpm); } #print "$line\n"; } closedir DH; } &outputnewest(%refrpms); } sub fileread($) { my $file = shift; my $VAR1; open FH, "<$file" or die "Couldn't open $file: $!"; my $data = do { local $/; ; }; close FH; eval $data; %refrpms = %{$VAR1}; &outputnewest(%refrpms); } sub serverread($) { my $server = shift; my $name; if ( $option{l} ) { open CH, "rpm -qa|" or die "Can't fork: $!"; } else { open CH, "ssh -x $server rpm -qa|" or die "Can't fork: $!"; } while ( ) { chomp; $name = $_; $name =~ s/(.*?)-([^-]*)-([^-]*)$/$1/; unless ( $option{q} ) { print "$_\n"; print "$name\n"; } push @{$instrpms{$name}}, $_; } close CH; } sub comparerpms() { my ( $correct, $installed ); foreach ( sort keys %instrpms ) { if ( exists $refrpms{$_} ) { $correct = @{$refrpms{$_}}[0]->{'FILENAME'}; $correct =~ s/\.(i[36]86|athlon|noarch)(\.rpm)?$//; foreach $installed ( @{$instrpms{$_}} ) { unless ( $correct eq $installed ) { print "\ncorrect: $correct\n"; print "installed: $installed\n"; } } } else { print "\n$_ doesn't exist in reference tree\n"; foreach my $rpm ( @{ $instrpms{$_} } ) { print " $rpm\n"; } } } } sub outputnewest(@) { my %allrpms = @_; if ( $option{q} ) { return; } foreach ( sort keys %allrpms) { # print scalar( @{$allrpms{$_}} ) . " $_\n"; if ( scalar( @{$allrpms{$_}} ) > 1 ) { @{$allrpms{$_}} = sort buildtimesort @{$allrpms{$_}}; # foreach my $rpm ( sort buildtimesort @{$allrpms{$_}} ) { # print " " . %{$rpm}->{'BUILDTIME'} . " " . %{$rpm}->{'FILENAME'} . "\n"; # } } print @{$allrpms{$_}}[0]->{'FILENAME'}."\n"; } } sub buildtimesort { my $a = %{$a}->{'BUILDTIME'}; my $b = %{$b}->{'BUILDTIME'}; if ( $a > $b ) { return -1; } else { return 1; } } sub splitname($$) { my $fullname = shift; my $packagename; my $version; my $build; my $arch; if ( $fullname =~ /(.*?)-([^-]*)-([^-]*)\.(i[36]86|athlon|noarch)(\.rpm)?$/ ) { $packagename = $1; $version = $2; $build =$3; $arch = $4; print "Fullname $fullname\n"; print " PACKAGE: $packagename\n"; print " VERSION: $version\n"; print " BUILD: $build\n"; print " ARCH: $arch\n"; return ( $packagename, $version, $build, $arch ); } else { print "The magic don't work for $fullname\n"; } } sub cmdline { getopts("f:hlo:pqs:", \%option); if ( $option{h} ) { &help; } unless ( $option{f} || $option{l} || $option{p} || $option{s} ) { &help; } if ( ( $option{f} && ( $option{p} || $option{o} ) ) || ( $option{l} && $option{s} ) ) { &help; } if ( $option{f} ) { &fileread($option{f}); } elsif ( $option{p} ) { &pathread; if ( $option{o} ) { open(FH, ">$option{o}") or die "Couldn't open $option{o}: $!"; print FH Dumper(\%refrpms); close(FH); } } if ( $option{l} ) { &serverread("localhost"); } elsif ( $option{s} ) { &serverread($option{s}); } if ( ( $option{f} || $option{p} ) && ( $option{l} || $option{s} ) ) { &comparerpms; } } sub help() { print << "EOT"; Usage: $0 [option] -f Read reference rpms from file -h Display this help -l Read installed rpms from localhost, overrides -s -o Write reference rpms to file, only useful in combination with -p -p Read rpms from build in mirror paths -q Quiet down a bit -s Read rpms from server Usually you'll want to run this program like $0 -p -o to build an index to compare you're systems to and then proceed with something like $0 -f -s for each server which you want to check the status of. EOT exit; } # sorteer routine die "menselijk" sorteerd; bijv.: # boneym100 elvis1 elvis2 elvis10 #sub wardsort { # my @a = split(/([0-9]+)/,$a); # my @b = split(/([0-9]+)/,$b); # # foreach my $x (@a) # { # my $y = shift @b; # my $r = ($x =~ /^[0-9]+$/ && $y =~ /^[0-9]+$/) ? # ($x <=> $y) : ($x cmp $y); # $r && return $r; # } # return -1 if (@b); # 0; #}