Annotation of loncom/build/CHECKRPMS.default, revision 1.14
1.1 harris41 1: #!/usr/bin/perl
2:
1.2 harris41 3: =pod
4:
5: =head1 NAME
6:
7: B<CHECKRPMS> - automated status report about RPMs on a system
8:
9: =head1 SYNOPSIS
10:
1.7 harris41 11: ./B<CHECKRPMS> [I<modeflag>]
1.2 harris41 12:
13: or
14:
1.7 harris41 15: B<perl> B<CHECKRPMS> [I<modeflag>]
16:
17: If I<modeflag> is left blank, the mode is "interactive". Otherwise,
18: other modes can be specified as shown in the listing below:
19:
20: =over 4
21:
1.8 harris41 22: =item DEFAULT
1.7 harris41 23:
1.8 harris41 24: When left blank, the script runs in interactive mode. First, a proposed
25: list of RPMs is presented to the user. Then, the user is asked if he or
26: she wants to download the RPMs to /tmp/loncapa_rpm_updates/.
1.7 harris41 27:
1.8 harris41 28: =item view
1.2 harris41 29:
1.8 harris41 30: A proposed list of RPMs to update is presented to the user.
1.2 harris41 31:
1.8 harris41 32: =item download
1.2 harris41 33:
1.8 harris41 34: A proposed set of RPMs to update are downloaded into /tmp/loncapa_rpm_updates/.
35: Note that prior information inside /tmp/loncapa_rpm_updates/ is removed.
1.2 harris41 36:
1.8 harris41 37: =item redownload
1.2 harris41 38:
1.8 harris41 39: A proposed set of RPMs to update are downloaded into /tmp/loncapa_rpm_updates/.
40: Note that prior information inside /tmp/loncapa_rpm_updates/ is not removed.
41: (This helps support continual attempts from dialup connections.)
1.2 harris41 42:
1.8 harris41 43: =item html
1.2 harris41 44:
1.8 harris41 45: Similar to view mode. XHTML-formatted output is delivered; presumably
46: to a web client. html mode is automatically chosen if $ENV{'QUERY_STRING'} is
47: defined.
1.2 harris41 48:
1.8 harris41 49: =back
1.2 harris41 50:
1.8 harris41 51: =head1 DESCRIPTION
1.2 harris41 52:
1.8 harris41 53: This file automates the usage of Martin Siegert's "check-rpms"
54: script. It runs through a list of possible mirror sites
55: until it finds one with a reasonably good FTP connection.
1.2 harris41 56:
1.8 harris41 57: For instructions on usage, see L<SYNOPSIS>.
1.2 harris41 58:
59: =head1 AUTHOR
60:
61: Scott Harrison, sharrison@users.sourceforge.net, 2002
62:
63: =cut
64:
1.7 harris41 65: # ================================================== READ IN COMMAND ARGUMENTS.
66:
1.4 harris41 67: # ---------------------------------------------------- Process download option.
1.7 harris41 68: my $argument = shift(@ARGV);
69: my $document;
70: my $mode;
71: if ($argument eq '--download' or $argument eq '--redownload')
1.4 harris41 72: {
73: if ($< != 0) # Download mode requires 'root'.
74: {
1.10 harris41 75: print(
1.7 harris41 76: '**** ERROR **** Download mode needs to be run as root'."\n");
77: exit(0); # Exit.
1.4 harris41 78: }
1.7 harris41 79: `rm -Rf /tmp/loncapa_rpm_updates` if $argument eq '--download';
1.4 harris41 80: $download='-v -dl -d /tmp/loncapa_rpm_updates'; # Part of check-rpms args.
1.7 harris41 81: $mode = 'download';
82: }
83: elsif ($argument eq '--view')
84: {
85: $mode = 'view';
86: }
87: elsif ($argument eq '--cronmail')
88: {
89: $mode = 'cronmail';
90: }
91: elsif ($ENV{'QUERY_STRING'} or $argument eq '--html')
92: {
93: $mode = 'html';
1.4 harris41 94: }
95: else
96: {
1.7 harris41 97: $mode = 'interactive';
1.4 harris41 98: }
99:
1.7 harris41 100: # ================================================== GENERAL INITIAL VARIABLES.
101: my $command_name=$0;
102:
1.2 harris41 103: # ---------------- The FTP servers (and their directory paths) to check against
1.5 harris41 104: my @serverpaths_to_try =
105: (
1.9 harris41 106: 'ftpmirror:loncapa@install.lon-capa.org/pub/redhat/linux/updates/',
107: 'mirror.pa.msu.edu/linux/redhat/linux/updates/',
1.7 harris41 108: 'distro.ibiblio.org/pub/linux/distributions/redhat/updates/',
109: 'limestone.uoregon.edu/redhat/updates/',
1.5 harris41 110: 'rufus.w3.org/linux/redhat/linux/updates/',
111: );
1.2 harris41 112:
1.7 harris41 113: # -------------------------------------------- Use check-rpms command this way.
1.5 harris41 114: my $checkcommand = 'check-rpms '.$download.' --rpmuser www -ftp';
1.2 harris41 115:
116: my $FTPSERVER; # ------------------------- the server portion of the serverpath
117: my $FTPUPDATES; # ----------------------------- the actual update root location
118: my @rpms; # ---------------------------------- this will store the list of RPMs
119: my $goodoutput; # ------------------------------------ good stuff was returned!
120: my $reallygoodoutput; # ------------------------------- you are 100% up-to-date
121:
1.7 harris41 122: # ===================================================== Control flow of output.
123: my $out = \*STDOUT; # Default: go to standard output (directly to terminal).
124:
125: if ($mode eq 'cronmail') # If cronmail mode, then save to file.
126: {
127: open(FOUT,'>/tmp/CHECKRPMS.'.$$);
128: $out = \*FOUT;
129: }
130:
131: $| = 1; # Flush to output whenever possible.
132:
133: # ========================================== Variables that must be defineable.
134:
135: # --------------------------------------------------- Determine RedHat version.
136: my $RHversion = (split /\s/, `cat /etc/redhat-release`)[4]; # - 6.2 or 7.3 or ?
137:
138: unless ($RHversion)
139: {
140: terminate($mode,$out,
141: '**** ERROR **** /etc/redhat-release not found'."\n".
142: 'This script does not appear to be running on RedHat.'."\n");
143: }
144:
1.2 harris41 145: # ----------------------------------------- Find the check-rpms script location
1.5 harris41 146: if (-e './check-rpms')
147: {
148: $commandpre='perl ./'; # Use the check-rpms in the current directory.
149: }
150: elsif (-e 'loncom/build/check-rpms')
151: {
1.7 harris41 152: $commandpre='perl loncom/build/'; # Use check-rpms in the loncom/build dir.
153: }
154: elsif (-e '/usr/local/loncapa/bin/check-rpms')
155: {
156: $commandpre='perl /usr/local/loncapa/bin/'; # Use /usr/local dir.
1.5 harris41 157: }
158: else # Cannot find check-rpms, so abort.
159: {
1.7 harris41 160: terminate($mode,$out,
161: '**** ERROR **** CANNOT FIND THE check-rpms SCRIPT'."\n");
1.5 harris41 162: }
1.2 harris41 163:
1.7 harris41 164: # Define check-rpms invocation based on the path to the check-rpms command.
1.5 harris41 165: $checkcommand = $commandpre.$checkcommand;
1.2 harris41 166:
1.7 harris41 167: # ============================================================= Initial output.
168:
169: print($out <<END) if $mode eq 'html';
170: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
171: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
172: <html>
173: <head>
174: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
175: <title>CHECKRPMS STATUS REPORT</title>
176: </head>
177: <body bgcolor="white">
178: <h1>CHECKRPMS STATUS REPORT</h1>
179: <hr />
180: <pre>
181: END
182:
1.5 harris41 183: # Notify user of current action.
1.7 harris41 184: print($out <<END);
1.2 harris41 185: THIS SCRIPT IS NOW PROBING SEVERAL FTP SERVERS....
186: PLEASE BE PATIENT, THIS MAY TAKE A FEW MINUTES.
187: END
188:
1.7 harris41 189: # ============== Go through all the servers until a decent connection is found.
1.5 harris41 190: SERVERLOOP: foreach my $serverpath (@serverpaths_to_try)
191: {
192: $serverpath=~/^(.*?)\//; # Pattern match the ip name.
193: $FTPSERVER=$1; # Set to the ip name.
1.9 harris41 194: $FTPSERVER_noauth=$FTPSERVER;
195: $FTPSERVER_noauth=~s/^.*?\@//;
196: print($out
197: "Trying $FTPSERVER_noauth...\n"); # Notify of attempts with ip name.
1.13 harris41 198: `ping -c 1 -w 10 $FTPSERVER_noauth 2>/dev/null`;#Ping ftp server (u there?)
1.5 harris41 199: if ($?==0) # If the ftp server can be pinged.
200: {
1.7 harris41 201: print($out "$FTPSERVER found...\n"); # Tell user ftp server is found.
1.5 harris41 202: `ncftpls ftp://$FTPSERVER`; # Try to access server with ftp protocol.
203: if ($?==0) # If the ftp server can be accessed with the ftp protocol.
204: {
205: $FTPUPDATES="$serverpath$RHversion/en/os"; # The full update path.
206: # Print the check-rpms command that will be executed.
1.7 harris41 207: print($out $checkcommand.' '.$FTPUPDATES."\n");
208: if ($mode eq 'download') # Was CHECKRPMS run in download mode?
1.5 harris41 209: {
210: $|=1; # Try to send things immediately to stdout; err umm....
211: # Tell the user about the /tmp/loncapa_rpm_updates directory.
1.7 harris41 212: print($out '**** NOTE **** '.
1.5 harris41 213: 'To check the status of the download, you can '.
214: 'periodically inspect the contents of the '.
215: '/tmp/loncapa_rpm_updates directory. '.
216: 'Please be patient; this download may take a while.'.
217: "\n");
218: # Do the download.
1.7 harris41 219: print($out `$checkcommand $FTPUPDATES 2>\&1`);
1.5 harris41 220: # Tell the user about what action they need to take with the
221: # downloaded RPMs.
1.7 harris41 222: print($out
223: 'You may now wish to visit the /tmp/loncapa_rpm_updates'.
1.5 harris41 224: ' directory and upgrade the RPMs. '."\n".
225: 'If this is a critical server (it is currently being'.
226: ' used for classes) and you do not know how to upgrade'.
227: ' RPMs, you should consult someone who has experience '.
228: 'with the "rpm" command.'."\n");
1.7 harris41 229: clean_exit($mode,$out,0); # Assume everything is okay and exit.
1.5 harris41 230: }
231: @rpms=`$checkcommand $FTPUPDATES 2>\&1`; # Read in list of RPMs.
232: # Create a text string that can be pattern matched.
1.2 harris41 233: my $rpmtext=join('',@rpms);
1.5 harris41 234: if ($rpmtext=~/You do not seem to have a/) # No www?
235: {
1.7 harris41 236: print($out "You do not have a 'www' user on your system.\n".
237: "Please add this user and try this command again.\n");
238: clean_exit($mode,$out,0);
1.5 harris41 239: }
240: if ($rpmtext=~/This account is currently not/) # ------------ uh-oh
241: {
1.7 harris41 242: print($out "...strange error, moving on ($FTPSERVER)\n");
1.5 harris41 243: }
244: else # --------------------------------------- the output is "good"
245: {
1.2 harris41 246: $goodoutput=$rpmtext;
1.5 harris41 247: unless (@rpms) # If there are no RPMs to update.
248: {
1.7 harris41 249: $reallygoodoutput = <<END;
1.2 harris41 250: **** NOTE **** All RPMS on your system appear to be up to date.
251: END
1.7 harris41 252: $goodoutput = ' ';
1.5 harris41 253: }
1.2 harris41 254: last SERVERLOOP;
1.5 harris41 255: }
256: }
1.7 harris41 257: print($out '...cannot establish an ftp session with '.$FTPSERVER."\n");
1.5 harris41 258: }
259: else
260: {
1.7 harris41 261: print($out "...cannot find $FTPSERVER on the network\n");
1.5 harris41 262: }
263: }
264: if (!$goodoutput) # If never received any useable output, assume "no server".
265: {
1.7 harris41 266: print($out '**** ERROR **** Cannot find a working ftp server.'."\n");
267: clean_exit($mode,$out,0);
1.5 harris41 268: }
269: elsif ($reallygoodoutput) # Everything is peachy keen and up-to-date already.
270: {
1.7 harris41 271: print($out $reallygoodoutput);
1.5 harris41 272: }
273: else # There are RPMs that need to be updated; show list to user.
274: {
275: my $rpmcount=scalar(@rpms); # Count up size of RPM list.
1.7 harris41 276: print($out <<END); # Print out an advisory warning to user.
1.4 harris41 277: **** WARNING **** You need to update at least $rpmcount RPMS shown in
1.1 harris41 278: the list below. THIS IS IMPORTANT FOR SECURITY.
279:
280: END
1.7 harris41 281: print($out $goodoutput); # Output the RPM list.
282: if ($mode eq 'interactive')
283: {
284: print($out <<END);
285: Do you want to download the RPMs listed above (y/n)?
286: END
287: my $in=<>;
288: if ($in=~/^y/)
289: {
290: print($out 'Please be patient... downloading into '.
291: '/tmp/loncapa_rpm_updates'."\n");
292: print($out `perl $command_name --download`);
293: clean_exit($mode,$out,0);
294: }
295: }
296: print($out <<END); # Output instructions to user about taking action.
1.1 harris41 297:
298: Please visit ftp://$FTPUPDATES
299: and download the RPMS you need.
300: For instructions on working with (and upgrading) RPMS, please
301: visit http://www.rpm.org/max-rpm/.
1.4 harris41 302: To automatically download these RPMs to /tmp/loncapa_rpm_updates/,
303: run the CHECKRPMS command as "./CHECKRPMS --download"
1.1 harris41 304: END
1.7 harris41 305: if ($mode eq 'cronmail')
306: {
307: print($out <<END); # Output more instructions to user.
308: CHECKRPMS should be located in /usr/local/loncapa/bin/.
309: END
310: }
311: }
312:
313: clean_exit($mode,$out,0);
314:
315: # ================================================================ Subroutines.
316:
317: sub clean_exit
318: {
319: my ($mode,$out,$code)=@_;
320:
321: if ($mode eq 'cronmail') # If cronmail mode, then mail LON-CAPA sys admin.
322: {
323: close(FOUT);
1.11 harris41 324:
1.7 harris41 325: # Read in configuration to get e-mail addresses.
326: my $perlvarref = read_conf('loncapa.conf');
327: my %perlvar = %{$perlvarref};
328: undef $perlvarref;
329: delete $perlvar{'lonReceipt'}; # remove since sensitive
330: delete $perlvar{'lonSqlAccess'}; # remove since sensitive
331:
332: # Set metadata for the e-mail.
333: my $emailto = "$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}";
1.11 harris41 334:
335: my $subj=$perlvar{'lonHostID'}.', RPMS to upgrade';
336:
337: # Make the e-mail's subject header to describe whether up-to-date.
338: if ($reallygoodoutput)
339: {
340: $subj = 'happy_lon: '.$subj; # Machine is up-to-date.
341: }
342: else
343: {
344: $subj = 'ALERT_lon: '.$subj; # There are out-of-date RPMs.
345: }
346:
347: # Send the e-mail.
1.14 ! harris41 348: my $date = `date +"\%e"`; # Always send a day after the "Ides" or after
! 349: # the beginning of a month. (In other words,
! 350: # send an e-mail every two weeks regardless.)
! 351: if (!$reallygoodoutput or
! 352: $date == 2 or
! 353: $date == 16)
1.12 albertel 354: {
355: system(
356: 'metasend -b -t '.$emailto.' -s '.
357: "'$subj' -f /tmp/CHECKRPMS.$$ -m text/plain");
358: }
1.7 harris41 359: }
360:
361: print($out <<END) if $mode eq 'html'; # If html mode, print ending tags.
362: </pre>
363: </body>
364: </html>
365: END
366: exit($code);
1.5 harris41 367: }
1.7 harris41 368:
369: sub terminate
370: {
371: my ($mode,$out,$output);
372: if ($mode eq 'html')
373: {
374: print($out <<END);
375: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
376: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
377: <html>
378: <head>
379: <meta http-equiv="Content-Type" content="text/html; charset=utf-8"></meta>
380: <title>CHECKRPMS ERROR</title>
381: </head>
382: <body bgcolor="white">
383: <h1>CHECKRPMS ERROR</h1>
384: <hr />
385: <p><font color="red"><font size="+1">
386: END
387: }
388: print($out $output);
389: if ($mode eq 'html')
390: {
391: print($out <<END);
392: </font></font></p></body></html>
393: END
394: }
395: }
396:
397:
398: # - read_conf: read LON-CAPA server configuration, especially PerlSetVar values
399: sub read_conf
400: {
401: my (@conf_files)=@_;
402: my %perlvar;
403: my $confdir='/etc/httpd/conf/';
404: foreach my $filename (@conf_files,'loncapa_apache.conf')
405: {
406: open(CONFIG,'<'.$confdir.$filename) or
407: die("Can't read $confdir$filename");
408: while (my $configline=<CONFIG>)
409: {
410: if ($configline =~ /^[^\#]*PerlSetVar/)
411: {
412: my ($unused,$varname,$varvalue)=split(/\s+/,$configline);
413: chomp($varvalue);
414: $perlvar{$varname}=$varvalue;
415: }
416: }
417: close(CONFIG);
418: }
419: my $perlvarref=\%perlvar;
420: return ($perlvarref);
421: }
422:
FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>