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