Annotation of loncom/build/CHECKRPMS, revision 1.18
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.18 ! raeburn 6: # $Id: CHECKRPMS,v 1.17 2017/04/09 14:54:02 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.18 ! raeburn 45: fedora, rhel >= 5, centos, scientific, oracle linux - 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.18 ! raeburn 142: } elsif ($distro =~ /^(centos|scientific|oracle)\d+$/) {
1.8 raeburn 143: $cmd = 'yum update';
144: &prepare_msg($tmpfile,$cmd);
145: ($send,$addsubj) = &check_with_yum($tmpfile);
1.11 raeburn 146: } elsif ($distro =~ /^(debian|ubuntu)\d+/) {
147: $cmd = 'apt-get upgrade';
148: &prepare_msg($tmpfile,$cmd);
149: ($send,$addsubj) = &check_with_apt($tmpfile);
1.1 raeburn 150: } else {
151: $cmd = '/usr/local/bin/check-rpms --update';
152: ($send,$addsubj) = &check_with_checkrpms($tmpfile);
153: }
154: if ($send) {
155: $subj .= $addsubj;
1.14 raeburn 156: if ($docroot ne '') {
157: system("cat $tmpfile > $docroot/lon-status/checkrpms.txt");
1.15 raeburn 158: if ($< == 0) {
159: system("chown www:www $docroot/lon-status/checkrpms.txt");
160: }
1.16 raeburn 161: chmod(0600,"$docroot/lon-status/checkrpms.txt");
1.14 raeburn 162: }
1.10 raeburn 163: system(qq{mail -s '$subj' "$emailto" < $tmpfile});
1.1 raeburn 164: }
165:
166: sub prepare_msg {
167: my ($tmpfile,$cmd) = @_;
168: #
169: # Put some nice text in $tmpfile
170: open(TMPFILE,">>$tmpfile");
171: print TMPFILE <<ENDHEADER;
172: Your system needs to be updated. Please execute (as root)
173:
174: $cmd
175:
176: to bring it up to date.
177:
1.5 raeburn 178: This is very important for the security of your server. The packages which need to be updated are listed below.
1.1 raeburn 179:
180: ENDHEADER
181: close(TMPFILE);
182: return;
183: }
184:
185: sub check_with_you {
186: my ($tmpfile) =@_;
187: my $you = '/usr/bin/online_update';
188: my $sendflag = 0;
189: my $append_to_subj;
190:
1.5 raeburn 191: if (open (PIPE, "$you -k -len 2>&1 |")) {
1.1 raeburn 192: my $output=<PIPE>;
193: close(PIPE);
194: chomp $output;
195: unless ($output eq 'No updates available.') {
1.5 raeburn 196: if (open (PIPE, "$you -s -d -len |grep ^INSTALL |")) {
197: my @updates = <PIPE>;
198: close(PIPE);
199: my $allpackages;
200: foreach my $line (@updates) {
201: my $package = substr($line,rindex($line,'/')+1);
202: if ($package ne '') {
203: $allpackages .= $package;
204: }
205: }
206: if ($allpackages ne '') {
207: open(TMPFILE,">>$tmpfile");
208: print TMPFILE $allpackages;
209: close(TMPFILE);
210: $sendflag = 1;
211: $append_to_subj = ' RPMS to upgrade';
212: }
213: } else {
214: $sendflag = 1;
215: $append_to_subj = ' Error running RPM update script';
216: }
1.1 raeburn 217: }
218: } else {
219: $sendflag = 1;
220: $append_to_subj = ' Error running RPM update script';
221: }
222: return ($sendflag,$append_to_subj);
223: }
224:
225: sub check_with_yum {
226: my ($tmpfile) = @_;
227: my $yum = '/usr/bin/yum';
228: my $sendflag = 0;
229: my $append_to_subj;
230:
231: #
232: # Execute yum command
233: my $command = $yum.' check-update '.'>>'.$tmpfile;
234: system($command);
235:
236: my $returnvalue = $?>>8;
237:
238: #
239: # Determine status of yum run
240: if (100 == $returnvalue) {
241: $sendflag = 1;
242: $append_to_subj = ' RPMS to upgrade';
243: } elsif (0 != $returnvalue) {
244: $sendflag = 1;
245: $append_to_subj = ' Error running RPM update script';
246: } else {
247: # yum returned 0, so everything is up to date.
248: }
249: return ($sendflag,$append_to_subj);
250: }
251:
1.17 raeburn 252: sub check_with_dnf {
253: my ($tmpfile) = @_;
254: my $dnf = '/usr/bin/dnf';
255: my $sendflag = 0;
256: my $append_to_subj;
257:
258: #
259: # Execute dnf command
260: my $command = $dnf.' check-update '.'>>'.$tmpfile;
261: system($command);
262:
263: my $returnvalue = $?>>8;
264:
265: #
266: # Determine status of dnf run
267: if (100 == $returnvalue) {
268: $sendflag = 1;
269: $append_to_subj = ' RPMS to upgrade';
270: } elsif (0 != $returnvalue) {
271: $sendflag = 1;
272: $append_to_subj = ' Error running RPM update script';
273: } else {
274: # dnf returned 0, so everything is up to date.
275: }
276: return ($sendflag,$append_to_subj);
277: }
278:
1.1 raeburn 279: sub check_with_up2date {
280: my ($tmpfile) = @_;
281: my $up2date = '/usr/bin/up2date-nox';
282: my $sendflag = 0;
283: my $append_to_subj;
284: #
285: # Execute online_update command to check for updates
286: my $up2date_error = 1;
287: if (open (PIPE, "$up2date -l 2>&1 |")) {
288: my @result=<PIPE>;
289: close(PIPE);
1.4 raeburn 290: my $output;
291: foreach my $line (@result) {
292: if ($line =~ /^The following Packages were marked to be skipped by your configuration:/) {
293: last;
294: } else {
295: $output .= $line;
296: }
297: }
1.1 raeburn 298: if (@result > 0) {
299: if ($output =~ /Fetching Obsoletes list/) {
300: $up2date_error = 0;
301: if ($output =~ /Name\s+Version\s+Rel\s+[\n\r\f]+\-+[\n\r\f]+(.+)/s) {
302: my $packagelist = $1;
1.4 raeburn 303: if ($packagelist ne '' && $packagelist !~ /^[\s\n\r\f]+$/) {
1.1 raeburn 304: open(TMPFILE,">>$tmpfile");
305: print TMPFILE $packagelist;
306: close(TMPFILE);
307: $append_to_subj = ' RPMS to upgrade';
308: $sendflag = 1;
309: }
310: }
311: }
312: }
313: }
314: if ($up2date_error) {
315: $append_to_subj = ' Error running RPM update script';
316: $sendflag = 1;
317: }
318: return ($sendflag,$append_to_subj);
319: }
320:
321: sub check_with_rug {
322: my ($tmpfile) = @_;
323: my $rug = '/usr/bin/rug';
324: my $sendflag = 0;
325: my $append_to_subj;
326: #
327: # Execute rug command to check for updates
328: if (open (PIPE, "$rug up -N 2>&1 |")) {
329: my @output=<PIPE>;
330: close(PIPE);
331: chomp(@output);
332: my @clean_output;
333: foreach my $line (@output) {
1.3 raeburn 334: if ($line =~ /^Waking\sup\sZMD\.\.\./) {
1.1 raeburn 335: next;
1.2 raeburn 336: } elsif ($line eq 'Done') {
337: next;
338: } elsif ($line eq '') {
339: next;
340: } elsif ($line eq 'The following packages will be installed:') {
341: next;
342: } elsif ($line eq 'Resolving Dependencies...') {
343: next;
344: } elsif ($line eq 'Transaction...') {
345: last;
346: } elsif ($line eq 'No updates are available.') {
1.1 raeburn 347: last;
1.5 raeburn 348: } elsif ($line eq 'Downloading Packages...') {
349: last;
1.1 raeburn 350: } else {
351: push(@clean_output,$line);
352: }
353: }
354: if (@clean_output > 0) {
355: open(TMPFILE,">>$tmpfile");
356: print TMPFILE join("\n",@clean_output);
357: close(TMPFILE);
358: $append_to_subj= ' RPMS to upgrade';
359: $sendflag = 1;
360: }
361: } else {
362: $append_to_subj = ' Error running RPM update check';
363: $sendflag = 1;
364: }
365: return ($sendflag,$append_to_subj);
366: }
367:
1.9 raeburn 368: sub check_with_zypper {
369: my ($tmpfile) = @_;
370: my $zypper = '/usr/bin/zypper';
371: my $sendflag = 0;
372: my $append_to_subj;
373: my $header;
374: #
375: # Execute zypper command to check for updates
376: if (open (PIPE, "$zypper lu 2>&1 |")) {
377: my @output=<PIPE>;
378: close(PIPE);
379: chomp(@output);
380: my @clean_output;
381: foreach my $line (@output) {
382: if ($line eq 'Restoring system sources...') {
383: next;
384: } elsif ($line =~ /^Parsing\smetadata\sfor\s/) {
385: next;
386: } elsif ($line eq 'Parsing RPM database...') {
387: next;
388: } elsif ($line =~ /^Catalog\s+\|\s+Name\s+\|\s+Version\s+\|\s+Category\s+\|\s+Status$/) {
389: $header = $line."\n";
390: next;
391: } elsif ($line =~ /^[-+]+$/) {
392: $header .= $line."\n";
393: next;
394: } elsif ($line eq 'WARNING: These are only the updates affecting the updater itself.') {
395: next;
396: } elsif ($line eq 'There are others available too.') {
397: next;
398: } else {
399: push(@clean_output,$line);
400: }
401: }
402: if (@clean_output > 0) {
403: open(TMPFILE,">>$tmpfile");
404: my $message = join("\n",@clean_output);
405: print TMPFILE $header.$message;
406: close(TMPFILE);
407: $append_to_subj= ' RPMS to upgrade';
408: $sendflag = 1;
409: }
410: } else {
411: $append_to_subj = ' Error running RPM update check';
412: $sendflag = 1;
413: }
414: return ($sendflag,$append_to_subj);
415: }
416:
1.11 raeburn 417: sub check_with_apt {
418: my ($tmpfile) = @_;
419: my $apt = '/usr/bin/apt-get';
420: my $sendflag = 0;
421: my $append_to_subj;
422: my $header;
423: my @chg_package;
424: #
425: # Execute apt-get command to update distributions
426: system ("$apt update > /dev/null");
427: my $returnvalue = $?>>8;
428: if ($returnvalue == 0) {
429: # Execute apt-get commands to check for upgrades
430: if (open (PIPE, "$apt -y --dry-run upgrade 2>&1 |")) {
431: my @output=<PIPE>;
432: close(PIPE);
433: chomp(@output);
434: foreach my $line (@output) {
435: $line =~ s/^\s+//;
436: my @items = split(/\s+/,$line);
437: if ($items[0] eq "Inst") {
438: push(@chg_package,$items[1]);
439: }
440: }
441: if (@chg_package > 0) {
442: $header = 'apt-get upgrade found the following packages need updating:'.
443: "\n\n";
444: open(TMPFILE,">>$tmpfile");
445: my $message = join("\n",@output);
446: print TMPFILE $header.$message;
447: close(TMPFILE);
448: $append_to_subj= ' deb packages to upgrade';
449: $sendflag = 1;
450: }
451: } else {
452: $append_to_subj = ' Error running deb upgrade check';
453: $sendflag = 1;
454: }
455: } else {
456: $append_to_subj = ' Error running deb update check';
457: $sendflag = 1;
458: }
459: return ($sendflag,$append_to_subj);
460: }
461:
1.1 raeburn 462: sub check_with_checkrpms {
463: my ($tmpfile,$perlvar) = @_;
464: my $checkrpms = '/usr/local/bin/check-rpms';
465: my $sendflag = 0;
466: my $append_to_subj;
467:
468: # Run Martin Seigert's checkrpms script. See
469: # See http://www.sfu.ca/acs/security/linux/check-rpms.html
470: # for more information.
471:
472: #
473: # Check that checkrpms is installed and is the proper version...
474: if (! -e $checkrpms) {
475: open(TMPFILE,">>$tmpfile");
476: print TMPFILE <<END;
477:
478: Unable to locate check-rpms on your system. Please go to
479: http://www.sfu.ca/acs/security/linux/check-rpms.html, download and
480: install check-rpms on this system.
481:
482: END
483: $append_to_subj = ' Error running RPM update check';
484: $sendflag = 1;
485: } else {
486: #
487: # Run check-rpms and capture its output
488: if (open (PIPE, "$checkrpms 2>&1 |")) {
489: my $output=<PIPE>;
490: close(PIPE);
491: if ($output ne '') {
492: $output = <<"END";
493:
494: checkrpms checked the status of the packages on your system and
495: produced the following output:
496: -------------------------------------------------------
497: $output
498: -------------------------------------------------------
499: If there are rpms which need to be installed, please log into
500: $perlvar->{'lonHostID'} and run the following command
501:
502: $checkrpms --update
503:
504: If there are kernel packages to be installed, use
505:
506: $checkrpms --update --install-kernel
507:
508: Keeping your system up to date is very important.
509: Ensuring you are using up to date software is a prerequisite for a
510: secure system.
511:
512: END
513: open(TMPFILE,">>$tmpfile");
514: print TMPFILE $output;
515: close(TMPFILE);
516: $append_to_subj = ' RPMS to upgrade';
517: $sendflag = 1;
518: }
519: }
520: }
521: return ($sendflag,$append_to_subj);
522: }
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>