#!/usr/bin/perl -w # # The LearningOnline Network with CAPA # Checks status of RPM packages on system. # # Copyright Michigan State University Board of Trustees # # This file is part of the LearningOnline Network with CAPA (LON-CAPA). # # LON-CAPA is free software; you can redistribute it and/or modify # it under the terms of the GNU General Public License as published by # the Free Software Foundation; either version 2 of the License, or # (at your option) any later version. # # LON-CAPA is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU General Public License for more details. # # You should have received a copy of the GNU General Public License # along with LON-CAPA; if not, write to the Free Software # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA # # /home/httpd/html/adm/gpl.txt # # http://www.lon-capa.org/ # =pod =head1 NAME B - automated status report about RPMs on a system. =head1 DESCRIPTION This file automates the process of checking for available updates to LON-CAPA systems. distprobe is used to determine the Linux distribution. The utility which is used to complete the check depends on the distro: fedora, rhel 5/5+, centos, scientific - yum suse 9.X and sles9 - you suse 10.2,10.3 - zypper sles10,suse10.1 - rug rhel 4 - up2date others - check-rpms Created by amalgamating previous distribution-specific CHECKRPMS.dist files (where dist was one of: fedora, rhel, suse, sles10, default). Must be run as root or www. =cut use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA::Configuration; use Apache::loncommon(); my $tmpfile = '/tmp/CHECKRPMS.'.$$; my $perlvar= LONCAPA::Configuration::read_conf('loncapa.conf'); # Determine who we email my $defdom = $perlvar->{'lonDefDomain'}; my $origmail = $perlvar->{'lonAdmEMail'}; my $emailto = &Apache::loncommon::build_recipient_list(undef, 'packagesmail',$defdom,$origmail); my $subj = $perlvar->{'lonHostID'}; # Get Linux distro open(PIPE, "$perlvar->{'lonDaemons'}/distprobe |"); my $distro = ; close(PIPE); undef($perlvar); my $hostname = `hostname`; chomp($hostname); open(TMPFILE,">$tmpfile"); print TMPFILE localtime(time).' '.$hostname."\n"; close(TMPFILE); my ($cmd,$send,$addsubj); if ($distro =~ /^fedora\d+$/) { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum($tmpfile); } elsif ($distro =~ /^(suse|sles)9\.?\d?$/) { $cmd = 'you'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_you($tmpfile); } elsif ($distro =~ /^suse10\.(\d)$/) { my $version =$1; if ($version > 1) { $cmd = 'zypper up'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_zypper($tmpfile); } else { $cmd = 'rug up'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_rug($tmpfile); } } elsif ($distro =~ /^sles10$/) { $cmd = 'rug up'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_rug($tmpfile); } elsif ($distro =~ /^rhes(\d+)$/) { my $version = $1; if ($version == 4) { $cmd ='up2date -u --nox'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_up2date($tmpfile); } elsif ($version > 4) { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum($tmpfile); } } elsif ($distro =~ /^centos\d+$/) { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum($tmpfile); } elsif ($distro =~ /^scientific\d+\.\d$/) { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum($tmpfile); } else { $cmd = '/usr/local/bin/check-rpms --update'; ($send,$addsubj) = &check_with_checkrpms($tmpfile); } if ($send) { $subj .= $addsubj; system(qq{mail -s '$subj' "$emailto" < $tmpfile}); } sub prepare_msg { my ($tmpfile,$cmd) = @_; # # Put some nice text in $tmpfile open(TMPFILE,">>$tmpfile"); print TMPFILE <&1 |")) { my $output=; close(PIPE); chomp $output; unless ($output eq 'No updates available.') { if (open (PIPE, "$you -s -d -len |grep ^INSTALL |")) { my @updates = ; close(PIPE); my $allpackages; foreach my $line (@updates) { my $package = substr($line,rindex($line,'/')+1); if ($package ne '') { $allpackages .= $package; } } if ($allpackages ne '') { open(TMPFILE,">>$tmpfile"); print TMPFILE $allpackages; close(TMPFILE); $sendflag = 1; $append_to_subj = ' RPMS to upgrade'; } } else { $sendflag = 1; $append_to_subj = ' Error running RPM update script'; } } } else { $sendflag = 1; $append_to_subj = ' Error running RPM update script'; } return ($sendflag,$append_to_subj); } sub check_with_yum { my ($tmpfile) = @_; my $yum = '/usr/bin/yum'; my $sendflag = 0; my $append_to_subj; # # Execute yum command my $command = $yum.' check-update '.'>>'.$tmpfile; system($command); my $returnvalue = $?>>8; # # Determine status of yum run if (100 == $returnvalue) { $sendflag = 1; $append_to_subj = ' RPMS to upgrade'; } elsif (0 != $returnvalue) { $sendflag = 1; $append_to_subj = ' Error running RPM update script'; } else { # yum returned 0, so everything is up to date. } return ($sendflag,$append_to_subj); } sub check_with_up2date { my ($tmpfile) = @_; my $up2date = '/usr/bin/up2date-nox'; my $sendflag = 0; my $append_to_subj; # # Execute online_update command to check for updates my $up2date_error = 1; if (open (PIPE, "$up2date -l 2>&1 |")) { my @result=; close(PIPE); my $output; foreach my $line (@result) { if ($line =~ /^The following Packages were marked to be skipped by your configuration:/) { last; } else { $output .= $line; } } if (@result > 0) { if ($output =~ /Fetching Obsoletes list/) { $up2date_error = 0; if ($output =~ /Name\s+Version\s+Rel\s+[\n\r\f]+\-+[\n\r\f]+(.+)/s) { my $packagelist = $1; if ($packagelist ne '' && $packagelist !~ /^[\s\n\r\f]+$/) { open(TMPFILE,">>$tmpfile"); print TMPFILE $packagelist; close(TMPFILE); $append_to_subj = ' RPMS to upgrade'; $sendflag = 1; } } } } } if ($up2date_error) { $append_to_subj = ' Error running RPM update script'; $sendflag = 1; } return ($sendflag,$append_to_subj); } sub check_with_rug { my ($tmpfile) = @_; my $rug = '/usr/bin/rug'; my $sendflag = 0; my $append_to_subj; # # Execute rug command to check for updates if (open (PIPE, "$rug up -N 2>&1 |")) { my @output=; close(PIPE); chomp(@output); my @clean_output; foreach my $line (@output) { if ($line =~ /^Waking\sup\sZMD\.\.\./) { next; } elsif ($line eq 'Done') { next; } elsif ($line eq '') { next; } elsif ($line eq 'The following packages will be installed:') { next; } elsif ($line eq 'Resolving Dependencies...') { next; } elsif ($line eq 'Transaction...') { last; } elsif ($line eq 'No updates are available.') { last; } elsif ($line eq 'Downloading Packages...') { last; } else { push(@clean_output,$line); } } if (@clean_output > 0) { open(TMPFILE,">>$tmpfile"); print TMPFILE join("\n",@clean_output); close(TMPFILE); $append_to_subj= ' RPMS to upgrade'; $sendflag = 1; } } else { $append_to_subj = ' Error running RPM update check'; $sendflag = 1; } return ($sendflag,$append_to_subj); } sub check_with_zypper { my ($tmpfile) = @_; my $zypper = '/usr/bin/zypper'; my $sendflag = 0; my $append_to_subj; my $header; # # Execute zypper command to check for updates if (open (PIPE, "$zypper lu 2>&1 |")) { my @output=; close(PIPE); chomp(@output); my @clean_output; foreach my $line (@output) { if ($line eq 'Restoring system sources...') { next; } elsif ($line =~ /^Parsing\smetadata\sfor\s/) { next; } elsif ($line eq 'Parsing RPM database...') { next; } elsif ($line =~ /^Catalog\s+\|\s+Name\s+\|\s+Version\s+\|\s+Category\s+\|\s+Status$/) { $header = $line."\n"; next; } elsif ($line =~ /^[-+]+$/) { $header .= $line."\n"; next; } elsif ($line eq 'WARNING: These are only the updates affecting the updater itself.') { next; } elsif ($line eq 'There are others available too.') { next; } else { push(@clean_output,$line); } } if (@clean_output > 0) { open(TMPFILE,">>$tmpfile"); my $message = join("\n",@clean_output); print TMPFILE $header.$message; close(TMPFILE); $append_to_subj= ' RPMS to upgrade'; $sendflag = 1; } } else { $append_to_subj = ' Error running RPM update check'; $sendflag = 1; } return ($sendflag,$append_to_subj); } sub check_with_checkrpms { my ($tmpfile,$perlvar) = @_; my $checkrpms = '/usr/local/bin/check-rpms'; my $sendflag = 0; my $append_to_subj; # Run Martin Seigert's checkrpms script. See # See http://www.sfu.ca/acs/security/linux/check-rpms.html # for more information. # # Check that checkrpms is installed and is the proper version... if (! -e $checkrpms) { open(TMPFILE,">>$tmpfile"); print TMPFILE <&1 |")) { my $output=; close(PIPE); if ($output ne '') { $output = <<"END"; checkrpms checked the status of the packages on your system and produced the following output: ------------------------------------------------------- $output ------------------------------------------------------- If there are rpms which need to be installed, please log into $perlvar->{'lonHostID'} and run the following command $checkrpms --update If there are kernel packages to be installed, use $checkrpms --update --install-kernel Keeping your system up to date is very important. Ensuring you are using up to date software is a prerequisite for a secure system. END open(TMPFILE,">>$tmpfile"); print TMPFILE $output; close(TMPFILE); $append_to_subj = ' RPMS to upgrade'; $sendflag = 1; } } } return ($sendflag,$append_to_subj); }