#!/usr/bin/perl # # The LearningOnline Network with CAPA # Checks status of RPM packages on system. # # $Id: CHECKRPMS,v 1.19 2019/10/23 20:34:39 raeburn Exp $ # # 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 (RHEL/Fedora/CentOS/Oracle Linux/SuSE/SLES) or debs (Debian/Ubuntu) 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 < 22; rhel (5, 6, 7); centos/scientific/oracle linux <=7 - yum fedora >= 22 - dnf rhel/centos/oracle linux >= 8 - dnf suse 9.X and sles9 - you suse 10.2, 10.3, 11.X and 12.X; sles (>= 11) - zypper sles10, suse10.1 - rug rhel 4 - up2date debian, ubuntu - apt-get 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'); my $docroot = $perlvar->{'lonDocRoot'}; # 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); if ($docroot ne '') { if (-e "$docroot/lon-status/checkrpms.txt") { unlink("$docroot/lon-status/checkrpms.txt"); } } my ($cmd,$send,$addsubj); if ($distro =~ /^fedora(\d+)$/) { my $version =$1; if ($version > 21) { $cmd = 'dnf update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum_or_dnf($tmpfile,'dnf'); } else { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum_or_dnf($tmpfile,'yum'); } } elsif ($distro =~ /^(suse|sles)9\.?\d?$/) { $cmd = 'you'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_you($tmpfile); } elsif ($distro =~ /^suse(\d{2,})\.(\d+)$/) { my $version =$1; my $subversion = $2; if (($version > 10) || (($version == 10) && ($subversion > 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 =~ /^sles(\d+)$/) { $cmd = 'zypper up'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_zypper($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 <= 7) { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum_or_dnf($tmpfile,'yum'); } else { $cmd = 'dnf update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum_or_dnf($tmpfile,'dnf'); } } elsif ($distro =~ /^(?:centos|scientific|oracle)(\d+)$/) { my $version = $1; if ($version <= 7) { $cmd = 'yum update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum_or_dnf($tmpfile,'yum'); } else { $cmd = 'dnf update'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_yum_or_dnf($tmpfile,'dnf'); } } elsif ($distro =~ /^(debian|ubuntu)\d+/) { $cmd = 'apt-get upgrade'; &prepare_msg($tmpfile,$cmd); ($send,$addsubj) = &check_with_apt($tmpfile); } else { $cmd = '/usr/local/bin/check-rpms --update'; ($send,$addsubj) = &check_with_checkrpms($tmpfile); } if ($send) { $subj .= $addsubj; if ($docroot ne '') { system("cat $tmpfile > $docroot/lon-status/checkrpms.txt"); if ($< == 0) { system("chown www:www $docroot/lon-status/checkrpms.txt"); } chmod(0600,"$docroot/lon-status/checkrpms.txt"); } 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_or_dnf { my ($tmpfile,$progname) = @_; my $path_to_exec = '/usr/bin/'; if ($progname eq 'dnf') { $path_to_exec .= $progname; } else { $path_to_exec .= 'yum'; } my $sendflag = 0; my $append_to_subj; # # Execute command my $command = $path_to_exec.' check-update '.'>>'.$tmpfile; system($command); my $returnvalue = $?>>8; # # Determine status of yum or dnf 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 or dnf 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_apt { my ($tmpfile) = @_; my $apt = '/usr/bin/apt-get'; my $sendflag = 0; my $append_to_subj; my $header; my @chg_package; # # Execute apt-get command to update distributions system ("$apt update > /dev/null"); my $returnvalue = $?>>8; if ($returnvalue == 0) { # Execute apt-get commands to check for upgrades if (open (PIPE, "$apt -y --dry-run upgrade 2>&1 |")) { my @output=; close(PIPE); chomp(@output); foreach my $line (@output) { $line =~ s/^\s+//; my @items = split(/\s+/,$line); if ($items[0] eq "Inst") { push(@chg_package,$items[1]); } } if (@chg_package > 0) { $header = 'apt-get upgrade found the following packages need updating:'. "\n\n"; open(TMPFILE,">>$tmpfile"); my $message = join("\n",@output); print TMPFILE $header.$message; close(TMPFILE); $append_to_subj= ' deb packages to upgrade'; $sendflag = 1; } } else { $append_to_subj = ' Error running deb upgrade check'; $sendflag = 1; } } else { $append_to_subj = ' Error running deb 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); } 500 Internal Server Error

Internal Server Error

The server encountered an internal error or misconfiguration and was unable to complete your request.

Please contact the server administrator at root@localhost to inform them of the time this error occurred, and the actions you performed just before this error.

More information about this error may be available in the server error log.