Annotation of loncom/build/CHECKRPMS, revision 1.15

1.11      raeburn     1: #!/usr/bin/perl
1.1       raeburn     2: #
                      3: # The LearningOnline Network with CAPA
                      4: # Checks status of RPM packages on system.
                      5: #
1.15    ! raeburn     6: # $Id: CHECKRPMS,v 1.14 2011/10/17 19:11:42 raeburn Exp $
1.13      raeburn     7: #
1.1       raeburn     8: # Copyright Michigan State University Board of Trustees
                      9: #
                     10: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                     11: #
                     12: # LON-CAPA is free software; you can redistribute it and/or modify
                     13: # it under the terms of the GNU General Public License as published by
                     14: # the Free Software Foundation; either version 2 of the License, or
                     15: # (at your option) any later version.
                     16: #
                     17: # LON-CAPA is distributed in the hope that it will be useful,
                     18: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     19: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     20: # GNU General Public License for more details.
                     21: #
                     22: # You should have received a copy of the GNU General Public License
                     23: # along with LON-CAPA; if not, write to the Free Software
                     24: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
                     25: #
                     26: # /home/httpd/html/adm/gpl.txt
                     27: #
                     28: # http://www.lon-capa.org/
                     29: #
                     30: 
                     31: =pod
                     32: 
                     33: =head1 NAME
                     34: 
1.11      raeburn    35: B<CHECKRPMS> - automated status report about RPMs (RHEL/Fedora/CentOS/SuSE) 
                     36:                or debs (Debian/Ubuntu) on a system. 
1.1       raeburn    37: 
                     38: =head1 DESCRIPTION
                     39: 
                     40: This file automates the process of checking for available updates
                     41: to LON-CAPA systems. distprobe is used to determine the Linux distribution.
                     42: 
                     43: The utility which is used to complete the check depends on the distro:
                     44: 
1.13      raeburn    45: fedora, rhel >= 5, centos, scientific - yum
1.1       raeburn    46: suse 9.X and sles9 - you
1.13      raeburn    47: suse 10.2,10.3,11.1,11.2,11.3,11.4,sles11 - zypper 
1.9       raeburn    48: sles10,suse10.1 - rug
1.1       raeburn    49: rhel 4 - up2date
1.11      raeburn    50: debian, ubuntu - apt-get
1.1       raeburn    51: others - check-rpms
                     52: 
                     53: Created by amalgamating previous distribution-specific CHECKRPMS.dist files (where dist was one of: fedora, rhel, suse, sles10, default).
                     54: 
                     55: Must be run as root or www.
                     56: 
                     57: =cut
                     58: 
                     59: use strict;
                     60: use lib '/home/httpd/lib/perl/';
                     61: use LONCAPA::Configuration;
1.10      raeburn    62: use Apache::loncommon();
1.1       raeburn    63: 
                     64: my $tmpfile = '/tmp/CHECKRPMS.'.$$;
                     65: my $perlvar= LONCAPA::Configuration::read_conf('loncapa.conf');
1.14      raeburn    66: my $docroot = $perlvar->{'lonDocRoot'};
1.1       raeburn    67: 
                     68: # Determine who we email
1.10      raeburn    69: my $defdom = $perlvar->{'lonDefDomain'};
                     70: my $origmail = $perlvar->{'lonAdmEMail'};
                     71: my $emailto = &Apache::loncommon::build_recipient_list(undef,
                     72:                                    'packagesmail',$defdom,$origmail);
1.1       raeburn    73: my $subj = $perlvar->{'lonHostID'};
                     74: 
                     75: # Get Linux distro
                     76: open(PIPE, "$perlvar->{'lonDaemons'}/distprobe |");
                     77: my $distro = <PIPE>;
                     78: close(PIPE);
                     79: 
                     80: undef($perlvar);
                     81: 
                     82: my $hostname = `hostname`;
                     83: chomp($hostname);
                     84: open(TMPFILE,">$tmpfile");
                     85: print TMPFILE localtime(time).'    '.$hostname."\n";
                     86: close(TMPFILE);
                     87: 
1.15    ! raeburn    88: if ($docroot ne '') {
        !            89:     if (-e "$docroot/lon-status/checkrpms.txt") {
        !            90:         unlink("$docroot/lon-status/checkrpms.txt");
        !            91:     }
        !            92: }
        !            93: 
1.1       raeburn    94: my ($cmd,$send,$addsubj);
                     95: if ($distro =~ /^fedora\d+$/) {
                     96:     $cmd = 'yum update';
                     97:     &prepare_msg($tmpfile,$cmd);
                     98:     ($send,$addsubj) = &check_with_yum($tmpfile);
1.6       albertel   99: } elsif ($distro =~ /^(suse|sles)9\.?\d?$/) {
1.1       raeburn   100:     $cmd = 'you';
                    101:     &prepare_msg($tmpfile,$cmd);
                    102:     ($send,$addsubj) = &check_with_you($tmpfile);
1.11      raeburn   103: } elsif ($distro =~ /^suse(\d{2,})\.(\d+)$/) {
1.9       raeburn   104:     my $version =$1;
1.11      raeburn   105:     my $subversion = $2;
                    106:     if (($version > 10) || (($version == 10) && ($subversion > 1))) { 
1.9       raeburn   107:         $cmd = 'zypper up';
                    108:         &prepare_msg($tmpfile,$cmd);
                    109:         ($send,$addsubj) = &check_with_zypper($tmpfile);
                    110:     } else {
                    111:         $cmd = 'rug up';
                    112:         &prepare_msg($tmpfile,$cmd);
                    113:         ($send,$addsubj) = &check_with_rug($tmpfile);
                    114:     }
                    115: } elsif ($distro =~ /^sles10$/) {
1.1       raeburn   116:     $cmd = 'rug up';
                    117:     &prepare_msg($tmpfile,$cmd);
                    118:     ($send,$addsubj) = &check_with_rug($tmpfile);
1.13      raeburn   119: } elsif ($distro =~ /^sles(\d+)$/) {
                    120:     $cmd = 'zypper up';
                    121:     &prepare_msg($tmpfile,$cmd);
                    122:     ($send,$addsubj) = &check_with_zypper($tmpfile);
1.7       raeburn   123: } elsif ($distro =~ /^rhes(\d+)$/) {
                    124:     my $version = $1;
                    125:     if ($version == 4) {
                    126:         $cmd ='up2date -u --nox';
                    127:         &prepare_msg($tmpfile,$cmd);
                    128:         ($send,$addsubj) = &check_with_up2date($tmpfile);
                    129:     } elsif ($version > 4) {
                    130:         $cmd = 'yum update';
                    131:         &prepare_msg($tmpfile,$cmd);
                    132:         ($send,$addsubj) = &check_with_yum($tmpfile);
                    133:     }
1.8       raeburn   134: } elsif ($distro =~ /^centos\d+$/) {
                    135:     $cmd = 'yum update';
                    136:     &prepare_msg($tmpfile,$cmd);
                    137:     ($send,$addsubj) = &check_with_yum($tmpfile);
1.12      raeburn   138: } elsif ($distro =~ /^scientific\d+$/) {
1.8       raeburn   139:     $cmd = 'yum update';
                    140:     &prepare_msg($tmpfile,$cmd);
                    141:     ($send,$addsubj) = &check_with_yum($tmpfile);
1.11      raeburn   142: } elsif ($distro =~ /^(debian|ubuntu)\d+/) {
                    143:     $cmd = 'apt-get upgrade';
                    144:     &prepare_msg($tmpfile,$cmd);
                    145:     ($send,$addsubj) = &check_with_apt($tmpfile);
1.1       raeburn   146: } else {
                    147:     $cmd = '/usr/local/bin/check-rpms --update';
                    148:     ($send,$addsubj) = &check_with_checkrpms($tmpfile);
                    149: }
                    150: if ($send) {
                    151:     $subj .= $addsubj;
1.14      raeburn   152:     if ($docroot ne '') {
                    153:         system("cat $tmpfile > $docroot/lon-status/checkrpms.txt");
1.15    ! raeburn   154:         if ($< == 0) {
        !           155:             system("chown www:www $docroot/lon-status/checkrpms.txt");
        !           156:         }
        !           157:         chmod(0600,$docroot/lon-status/checkrpms.txt");
1.14      raeburn   158:     }
1.10      raeburn   159:     system(qq{mail -s '$subj' "$emailto" < $tmpfile});
1.1       raeburn   160: }
                    161: 
                    162: sub prepare_msg {
                    163:     my ($tmpfile,$cmd) = @_;
                    164:     #
                    165:     # Put some nice text in $tmpfile
                    166:     open(TMPFILE,">>$tmpfile");
                    167:     print TMPFILE <<ENDHEADER;
                    168: Your system needs to be updated.  Please execute (as root)
                    169: 
                    170: $cmd
                    171: 
                    172: to bring it up to date.
                    173: 
1.5       raeburn   174: This is very important for the security of your server.  The packages which need to be updated are listed below.
1.1       raeburn   175: 
                    176: ENDHEADER
                    177:     close(TMPFILE);
                    178:     return;
                    179: }
                    180: 
                    181: sub check_with_you {
                    182:     my ($tmpfile) =@_;
                    183:     my $you = '/usr/bin/online_update';
                    184:     my $sendflag = 0;
                    185:     my $append_to_subj;
                    186: 
1.5       raeburn   187:     if (open (PIPE, "$you -k -len 2>&1 |")) {
1.1       raeburn   188:         my $output=<PIPE>;
                    189:         close(PIPE);
                    190:         chomp $output;
                    191:         unless ($output eq 'No updates available.') {
1.5       raeburn   192:             if (open (PIPE, "$you -s -d -len |grep ^INSTALL |")) {
                    193:                 my @updates = <PIPE>;
                    194:                 close(PIPE);
                    195:                 my $allpackages;
                    196:                 foreach my $line (@updates) {
                    197:                     my $package = substr($line,rindex($line,'/')+1);
                    198:                     if ($package ne '') {
                    199:                         $allpackages .= $package;
                    200:                     }
                    201:                 }
                    202:                 if ($allpackages ne '') {
                    203:                     open(TMPFILE,">>$tmpfile");
                    204:                     print TMPFILE $allpackages;
                    205:                     close(TMPFILE);
                    206:                     $sendflag = 1;
                    207:                     $append_to_subj = ' RPMS to upgrade';
                    208:                 }
                    209:             } else {
                    210:                 $sendflag = 1;
                    211:                 $append_to_subj = ' Error running RPM update script';
                    212:             }
1.1       raeburn   213:         }
                    214:     } else {
                    215:         $sendflag = 1;
                    216:         $append_to_subj = ' Error running RPM update script';
                    217:     }
                    218:     return ($sendflag,$append_to_subj);
                    219: }
                    220: 
                    221: sub check_with_yum {
                    222:     my ($tmpfile) = @_;
                    223:     my $yum = '/usr/bin/yum';
                    224:     my $sendflag = 0;
                    225:     my $append_to_subj;
                    226: 
                    227:     #
                    228:     # Execute yum command
                    229:     my $command = $yum.' check-update '.'>>'.$tmpfile;
                    230:     system($command);
                    231: 
                    232:     my $returnvalue = $?>>8;
                    233: 
                    234:     #
                    235:     # Determine status of yum run
                    236:     if (100 == $returnvalue) {
                    237:         $sendflag = 1;
                    238:         $append_to_subj = ' RPMS to upgrade';
                    239:     } elsif (0 != $returnvalue) {
                    240:         $sendflag = 1;
                    241:         $append_to_subj = ' Error running RPM update script';
                    242:     } else {
                    243:         # yum returned 0, so everything is up to date.
                    244:     }
                    245:     return ($sendflag,$append_to_subj);
                    246: }
                    247: 
                    248: sub check_with_up2date {
                    249:     my ($tmpfile) = @_;
                    250:     my $up2date = '/usr/bin/up2date-nox';
                    251:     my $sendflag = 0;
                    252:     my $append_to_subj;
                    253:     #
                    254:     # Execute online_update command to check for updates
                    255:     my $up2date_error = 1;
                    256:     if (open (PIPE, "$up2date -l 2>&1 |")) {
                    257:         my @result=<PIPE>;
                    258:         close(PIPE);
1.4       raeburn   259:         my $output; 
                    260:         foreach my $line (@result) {
                    261:             if ($line =~ /^The following Packages were marked to be skipped by your configuration:/) {
                    262:                 last;
                    263:             } else {
                    264:                 $output .= $line;
                    265:             }
                    266:         } 
1.1       raeburn   267:         if (@result > 0) {
                    268:             if ($output =~ /Fetching Obsoletes list/) {
                    269:                 $up2date_error = 0;
                    270:                 if ($output =~ /Name\s+Version\s+Rel\s+[\n\r\f]+\-+[\n\r\f]+(.+)/s) {
                    271:                     my $packagelist = $1;
1.4       raeburn   272:                     if ($packagelist ne '' && $packagelist !~ /^[\s\n\r\f]+$/) {
1.1       raeburn   273:                         open(TMPFILE,">>$tmpfile");
                    274:                         print TMPFILE $packagelist;
                    275:                         close(TMPFILE);
                    276:                         $append_to_subj = ' RPMS to upgrade';
                    277:                         $sendflag = 1;
                    278:                     }
                    279:                 }
                    280:             }
                    281:         }
                    282:     }
                    283:     if ($up2date_error) {
                    284:         $append_to_subj = ' Error running RPM update script';
                    285:         $sendflag = 1;
                    286:     }
                    287:     return ($sendflag,$append_to_subj);
                    288: }
                    289: 
                    290: sub check_with_rug {
                    291:     my ($tmpfile) = @_;
                    292:     my $rug = '/usr/bin/rug';
                    293:     my $sendflag = 0;
                    294:     my $append_to_subj;
                    295:     #
                    296:     # Execute rug command to check for updates
                    297:     if (open (PIPE, "$rug up -N 2>&1 |")) {
                    298:         my @output=<PIPE>;
                    299:         close(PIPE);
                    300:         chomp(@output);
                    301:         my @clean_output;
                    302:         foreach my $line (@output) {
1.3       raeburn   303:             if ($line =~ /^Waking\sup\sZMD\.\.\./) {
1.1       raeburn   304:                 next;
1.2       raeburn   305:             } elsif ($line eq 'Done') {
                    306:                 next;
                    307:             } elsif ($line eq '') {
                    308:                 next;
                    309:             } elsif ($line eq 'The following packages will be installed:') {
                    310:                 next;
                    311:             } elsif ($line eq 'Resolving Dependencies...') {
                    312:                 next;
                    313:             } elsif ($line eq 'Transaction...') {
                    314:                 last;
                    315:             } elsif ($line eq 'No updates are available.') {
1.1       raeburn   316:                 last;
1.5       raeburn   317:             } elsif ($line eq 'Downloading Packages...') {
                    318:                 last;
1.1       raeburn   319:             } else {
                    320:                 push(@clean_output,$line);
                    321:             }
                    322:         }
                    323:         if (@clean_output > 0) {
                    324:             open(TMPFILE,">>$tmpfile");
                    325:             print TMPFILE join("\n",@clean_output);
                    326:             close(TMPFILE);
                    327:             $append_to_subj= ' RPMS to upgrade';
                    328:             $sendflag = 1;
                    329:          }
                    330:     } else {
                    331:         $append_to_subj = ' Error running RPM update check';
                    332:         $sendflag = 1;
                    333:     }
                    334:     return ($sendflag,$append_to_subj);
                    335: }
                    336: 
1.9       raeburn   337: sub check_with_zypper {
                    338:     my ($tmpfile) = @_;
                    339:     my $zypper = '/usr/bin/zypper';
                    340:     my $sendflag = 0;
                    341:     my $append_to_subj;
                    342:     my $header;
                    343:     #
                    344:     # Execute zypper command to check for updates
                    345:     if (open (PIPE, "$zypper lu 2>&1 |")) {
                    346:         my @output=<PIPE>;
                    347:         close(PIPE);
                    348:         chomp(@output);
                    349:         my @clean_output;
                    350:         foreach my $line (@output) {
                    351:             if ($line eq 'Restoring system sources...') {
                    352:                 next;
                    353:             } elsif ($line =~ /^Parsing\smetadata\sfor\s/) {
                    354:                 next;
                    355:             } elsif ($line eq 'Parsing RPM database...') {
                    356:                 next;
                    357:             } elsif ($line  =~ /^Catalog\s+\|\s+Name\s+\|\s+Version\s+\|\s+Category\s+\|\s+Status$/) {
                    358:                 $header = $line."\n";
                    359:                 next;
                    360:             } elsif ($line =~ /^[-+]+$/) {
                    361:                 $header .= $line."\n";
                    362:                 next;
                    363:             } elsif ($line eq 'WARNING: These are only the updates affecting the updater itself.') {
                    364:                 next;
                    365:             } elsif ($line eq 'There are others available too.') {
                    366:                 next;
                    367:             } else {
                    368:                 push(@clean_output,$line);
                    369:             }
                    370:         }
                    371:         if (@clean_output > 0) {
                    372:             open(TMPFILE,">>$tmpfile");
                    373:             my $message = join("\n",@clean_output);
                    374:             print TMPFILE $header.$message;
                    375:             close(TMPFILE);
                    376:             $append_to_subj= ' RPMS to upgrade';
                    377:             $sendflag = 1;
                    378:         }
                    379:     } else {
                    380:         $append_to_subj = ' Error running RPM update check';
                    381:         $sendflag = 1;
                    382:     }
                    383:     return ($sendflag,$append_to_subj);
                    384: }
                    385: 
1.11      raeburn   386: sub check_with_apt {
                    387:     my ($tmpfile) = @_;
                    388:     my $apt = '/usr/bin/apt-get';
                    389:     my $sendflag = 0;
                    390:     my $append_to_subj;
                    391:     my $header;
                    392:     my @chg_package;
                    393:     #
                    394:     # Execute apt-get command to update distributions
                    395:     system ("$apt update > /dev/null");
                    396:     my $returnvalue = $?>>8;
                    397:     if ($returnvalue == 0) {
                    398:         # Execute apt-get commands to check for upgrades
                    399:         if (open (PIPE, "$apt -y --dry-run upgrade  2>&1 |")) {
                    400:             my @output=<PIPE>;
                    401:             close(PIPE);
                    402:             chomp(@output);
                    403:             foreach my $line (@output) {
                    404:                 $line =~ s/^\s+//;
                    405:                 my @items = split(/\s+/,$line);
                    406:                 if ($items[0] eq "Inst") {
                    407:                     push(@chg_package,$items[1]);
                    408:                 }
                    409:             }
                    410:             if (@chg_package > 0) {
                    411:                 $header = 'apt-get upgrade found the following packages need updating:'.
                    412:                           "\n\n";
                    413:                 open(TMPFILE,">>$tmpfile");
                    414:                 my $message = join("\n",@output);
                    415:                 print TMPFILE $header.$message;
                    416:                 close(TMPFILE);
                    417:                 $append_to_subj= ' deb packages to upgrade';
                    418:                 $sendflag = 1;
                    419:             }
                    420:         } else {
                    421:             $append_to_subj = ' Error running deb upgrade check';
                    422:             $sendflag = 1;
                    423:         }
                    424:     } else {
                    425:         $append_to_subj = ' Error running deb update check';
                    426:         $sendflag = 1;
                    427:     }
                    428:     return ($sendflag,$append_to_subj);
                    429: }
                    430: 
1.1       raeburn   431: sub check_with_checkrpms {
                    432:     my ($tmpfile,$perlvar) = @_;
                    433:     my $checkrpms = '/usr/local/bin/check-rpms';
                    434:     my $sendflag = 0;
                    435:     my $append_to_subj;
                    436: 
                    437:     # Run Martin Seigert's checkrpms script.  See
                    438:     # See http://www.sfu.ca/acs/security/linux/check-rpms.html 
                    439:     # for more information.
                    440: 
                    441:     #
                    442:     # Check that checkrpms is installed and is the proper version...
                    443:     if (! -e $checkrpms) {
                    444:        open(TMPFILE,">>$tmpfile");
                    445:        print TMPFILE <<END;
                    446: 
                    447: Unable to locate check-rpms on your system.  Please go to
                    448: http://www.sfu.ca/acs/security/linux/check-rpms.html, download and
                    449: install check-rpms on this system.
                    450: 
                    451: END
                    452:         $append_to_subj = ' Error running RPM update check';
                    453:         $sendflag = 1; 
                    454:     } else {
                    455:         #
                    456:         # Run check-rpms and capture its output
                    457:         if (open (PIPE, "$checkrpms 2>&1 |")) {
                    458:             my $output=<PIPE>;
                    459:             close(PIPE);
                    460:             if ($output ne '') {
                    461:                 $output = <<"END";
                    462: 
                    463: checkrpms checked the status of the packages on your system and
                    464: produced the following output:
                    465: -------------------------------------------------------
                    466: $output
                    467: -------------------------------------------------------
                    468: If there are rpms which need to be installed, please log into
                    469: $perlvar->{'lonHostID'} and run the following command
                    470: 
                    471: $checkrpms --update
                    472: 
                    473: If there are kernel packages to be installed, use
                    474: 
                    475: $checkrpms --update --install-kernel
                    476: 
                    477: Keeping your system up to date is very important.
                    478: Ensuring you are using up to date software is a prerequisite for a
                    479: secure system.
                    480: 
                    481: END
                    482:                 open(TMPFILE,">>$tmpfile");
                    483:                 print TMPFILE $output;
                    484:                 close(TMPFILE);
                    485:                 $append_to_subj = ' RPMS to upgrade';
                    486:                 $sendflag = 1; 
                    487:             }
                    488:         }
                    489:     }
                    490:     return ($sendflag,$append_to_subj);
                    491: }

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>