Annotation of loncom/loncron, revision 1.110

1.1       albertel    1: #!/usr/bin/perl
                      2: 
1.47      albertel    3: # Housekeeping program, started by cron, loncontrol and loncron.pl
                      4: #
1.110   ! raeburn     5: # $Id: loncron,v 1.109 2018/10/25 02:48:56 raeburn Exp $
1.47      albertel    6: #
                      7: # Copyright Michigan State University Board of Trustees
                      8: #
                      9: # This file is part of the LearningOnline Network with CAPA (LON-CAPA).
                     10: #
                     11: # LON-CAPA is free software; you can redistribute it and/or modify
                     12: # it under the terms of the GNU General Public License as published by
                     13: # the Free Software Foundation; either version 2 of the License, or
                     14: # (at your option) any later version.
                     15: #
                     16: # LON-CAPA is distributed in the hope that it will be useful,
                     17: # but WITHOUT ANY WARRANTY; without even the implied warranty of
                     18: # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
                     19: # GNU General Public License for more details.
                     20: #
                     21: # You should have received a copy of the GNU General Public License
                     22: # along with LON-CAPA; if not, write to the Free Software
                     23: # Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
                     24: #
                     25: # /home/httpd/html/adm/gpl.txt
                     26: #
                     27: # http://www.lon-capa.org/
1.1       albertel   28: #
1.24      www        29: 
                     30: $|=1;
1.48      albertel   31: use strict;
1.1       albertel   32: 
1.26      harris41   33: use lib '/home/httpd/lib/perl/';
                     34: use LONCAPA::Configuration;
1.96      raeburn    35: use LONCAPA::Checksumming;
1.89      raeburn    36: use LONCAPA;
1.72      albertel   37: use Apache::lonnet;
1.79      raeburn    38: use Apache::loncommon;
1.26      harris41   39: 
1.1       albertel   40: use IO::File;
                     41: use IO::Socket;
1.48      albertel   42: use HTML::Entities;
1.49      albertel   43: use Getopt::Long;
1.104     raeburn    44: use GDBM_File;
                     45: use Storable qw(thaw);
1.46      albertel   46: #globals
                     47: use vars qw (%perlvar %simplestatus $errors $warnings $notices $totalcount);
                     48: 
                     49: my $statusdir="/home/httpd/html/lon-status";
                     50: 
1.1       albertel   51: 
                     52: # --------------------------------------------------------- Output error status
                     53: 
1.46      albertel   54: sub log {
                     55:     my $fh=shift;
                     56:     if ($fh) {	print $fh @_  }
                     57: }
                     58: 
1.1       albertel   59: sub errout {
                     60:    my $fh=shift;
1.46      albertel   61:    &log($fh,(<<ENDERROUT));
1.48      albertel   62:      <table border="2" bgcolor="#CCCCCC">
1.1       albertel   63:      <tr><td>Notices</td><td>$notices</td></tr>
                     64:      <tr><td>Warnings</td><td>$warnings</td></tr>
                     65:      <tr><td>Errors</td><td>$errors</td></tr>
1.48      albertel   66:      </table><p><a href="#top">Top</a></p>
1.1       albertel   67: ENDERROUT
                     68: }
                     69: 
1.73      albertel   70: sub rotate_logfile {
                     71:     my ($file,$fh,$description) = @_;
                     72:     my $size=(stat($file))[7];
                     73:     if ($size>40000) {
                     74: 	&log($fh,"<p>Rotating $description ...</p>");
                     75: 	rename("$file.2","$file.3");
                     76: 	rename("$file.1","$file.2");
                     77: 	rename("$file","$file.1");
                     78:     } 
                     79: }
                     80: 
1.42      albertel   81: sub start_daemon {
1.50      albertel   82:     my ($fh,$daemon,$pidfile,$args) = @_;
1.44      albertel   83:     my $progname=$daemon;
1.71      albertel   84:     if ($daemon eq 'lonc') {
1.44      albertel   85: 	$progname='loncnew'; 
                     86:     }
1.51      albertel   87:     my $error_fname="$perlvar{'lonDaemons'}/logs/${daemon}_errors";
1.73      albertel   88:     &rotate_logfile($error_fname,$fh,'error logs');
1.74      albertel   89:     if ($daemon eq 'lonc') {
                     90: 	&clean_sockets($fh);
                     91:     }
1.51      albertel   92:     system("$perlvar{'lonDaemons'}/$progname 2>$perlvar{'lonDaemons'}/logs/${daemon}_errors");
1.60      albertel   93:     sleep 1;
1.42      albertel   94:     if (-e $pidfile) {
1.48      albertel   95: 	&log($fh,"<p>Seems like it started ...</p>");
1.42      albertel   96: 	my $lfh=IO::File->new("$pidfile");
                     97: 	my $daemonpid=<$lfh>;
                     98: 	chomp($daemonpid);
1.62      albertel   99: 	if ($daemonpid =~ /^\d+$/ && kill 0 => $daemonpid) {
1.42      albertel  100: 	    return 1;
                    101: 	} else {
                    102: 	    return 0;
                    103: 	}
                    104:     }
1.48      albertel  105:     &log($fh,"<p>Seems like that did not work!</p>");
1.42      albertel  106:     $errors++;
                    107:     return 0;
                    108: }
                    109: 
                    110: sub checkon_daemon {
1.59      albertel  111:     my ($fh,$daemon,$maxsize,$send,$args)=@_;
1.42      albertel  112: 
1.63      albertel  113:     my $result;
1.48      albertel  114:     &log($fh,'<hr /><a name="'.$daemon.'" /><h2>'.$daemon.'</h2><h3>Log</h3><p style="white-space: pre;"><tt>');
1.57      albertel  115:     printf("%-15s ",$daemon);
1.110   ! raeburn   116:     if ($fh) {
        !           117:         if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){
        !           118: 	    if (open(DFH,"tail -n25 $perlvar{'lonDaemons'}/logs/$daemon.log|")) {
        !           119: 	        while (my $line=<DFH>) { 
        !           120: 	            &log($fh,"$line");
        !           121: 	            if ($line=~/INFO/) { $notices++; }
        !           122: 	            if ($line=~/WARNING/) { $notices++; }
        !           123: 	            if ($line=~/CRITICAL/) { $warnings++; }
        !           124: 	        }
        !           125: 	        close (DFH);
        !           126:             }
        !           127:         }
        !           128:         &log($fh,"</tt></p>");
1.42      albertel  129:     }
                    130:     
                    131:     my $pidfile="$perlvar{'lonDaemons'}/logs/$daemon.pid";
                    132:     
                    133:     my $restartflag=1;
1.46      albertel  134:     my $daemonpid;
1.42      albertel  135:     if (-e $pidfile) {
                    136: 	my $lfh=IO::File->new("$pidfile");
1.46      albertel  137: 	$daemonpid=<$lfh>;
1.42      albertel  138: 	chomp($daemonpid);
1.62      albertel  139: 	if ($daemonpid =~ /^\d+$/ && kill 0 => $daemonpid) {
1.46      albertel  140: 	    &log($fh,"<h3>$daemon at pid $daemonpid responding");
1.59      albertel  141: 	    if ($send) { &log($fh,", sending $send"); }
1.46      albertel  142: 	    &log($fh,"</h3>");
1.59      albertel  143: 	    if ($send eq 'USR1') { kill USR1 => $daemonpid; }
                    144: 	    if ($send eq 'USR2') { kill USR2 => $daemonpid; }
1.42      albertel  145: 	    $restartflag=0;
1.59      albertel  146: 	    if ($send eq 'USR2') {
1.63      albertel  147: 		$result = 'reloaded';
1.59      albertel  148: 		print "reloaded\n";
                    149: 	    } else {
1.63      albertel  150: 		$result = 'running';
1.59      albertel  151: 		print "running\n";
                    152: 	    }
1.42      albertel  153: 	} else {
                    154: 	    $errors++;
1.46      albertel  155: 	    &log($fh,"<h3>$daemon at pid $daemonpid not responding</h3>");
1.42      albertel  156: 	    $restartflag=1;
1.46      albertel  157: 	    &log($fh,"<h3>Decided to clean up stale .pid file and restart $daemon</h3>");
1.42      albertel  158: 	}
                    159:     }
                    160:     if ($restartflag==1) {
                    161: 	$simplestatus{$daemon}='off';
                    162: 	$errors++;
1.57      albertel  163: 	my $kadaemon=$daemon;
                    164: 	if ($kadaemon eq 'lonmemcached') { $kadaemon='memcached'; }
1.101     raeburn   165: 	&log($fh,'<br /><font color="red">Killall '.$daemon.': '.
1.57      albertel  166: 	    `killall $kadaemon 2>&1`.' - ');
1.60      albertel  167: 	sleep 1;
1.46      albertel  168: 	&log($fh,unlink($pidfile).' - '.
1.57      albertel  169: 	    `killall -9 $kadaemon 2>&1`.
1.101     raeburn   170: 	    '</font><br />');
1.107     raeburn   171:         if ($kadaemon eq 'loncnew') {
                    172:             &clean_lonc_childpids();
                    173:         }
1.46      albertel  174: 	&log($fh,"<h3>$daemon not running, trying to start</h3>");
1.110   ! raeburn   175: 
1.50      albertel  176: 	if (&start_daemon($fh,$daemon,$pidfile,$args)) {
1.46      albertel  177: 	    &log($fh,"<h3>$daemon at pid $daemonpid responding</h3>");
1.42      albertel  178: 	    $simplestatus{$daemon}='restarted';
1.63      albertel  179: 	    $result = 'started';
1.42      albertel  180: 	    print "started\n";
                    181: 	} else {
                    182: 	    $errors++;
1.46      albertel  183: 	    &log($fh,"<h3>$daemon at pid $daemonpid not responding</h3>");
1.48      albertel  184: 	    &log($fh,"<p>Give it one more try ...</p>");
1.42      albertel  185: 	    print " ";
1.50      albertel  186: 	    if (&start_daemon($fh,$daemon,$pidfile,$args)) {
1.46      albertel  187: 		&log($fh,"<h3>$daemon at pid $daemonpid responding</h3>");
1.42      albertel  188: 		$simplestatus{$daemon}='restarted';
1.63      albertel  189: 		$result = 'started';
1.42      albertel  190: 		print "started\n";
                    191: 	    } else {
1.63      albertel  192: 		$result = 'failed';
1.42      albertel  193: 		print " failed\n";
                    194: 		$simplestatus{$daemon}='failed';
                    195: 		$errors++; $errors++;
1.46      albertel  196: 		&log($fh,"<h3>$daemon at pid $daemonpid not responding</h3>");
1.48      albertel  197: 		&log($fh,"<p>Unable to start $daemon</p>");
1.42      albertel  198: 	    }
                    199: 	}
1.110   ! raeburn   200:         if ($fh) {
        !           201: 	    if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){
        !           202: 	        &log($fh,"<p><pre>");
        !           203: 	        if (open(DFH,"tail -n100 $perlvar{'lonDaemons'}/logs/$daemon.log|")) {
        !           204: 	            while (my $line=<DFH>) { 
        !           205: 		        &log($fh,"$line");
        !           206: 		        if ($line=~/WARNING/) { $notices++; }
        !           207: 		        if ($line=~/CRITICAL/) { $notices++; }
        !           208: 	            }
        !           209: 	            close (DFH);
        !           210:                 }
        !           211: 	        &log($fh,"</pre></p>");
        !           212:             }
1.42      albertel  213: 	}
                    214:     }
                    215:     
1.46      albertel  216:     my $fname="$perlvar{'lonDaemons'}/logs/$daemon.log";
1.73      albertel  217:     &rotate_logfile($fname,$fh,'logs');
1.42      albertel  218: 
                    219:     &errout($fh);
1.63      albertel  220:     return $result;
1.42      albertel  221: }
1.1       albertel  222: 
1.46      albertel  223: # --------------------------------------------------------------------- Machine
                    224: sub log_machine_info {
                    225:     my ($fh)=@_;
1.48      albertel  226:     &log($fh,'<hr /><a name="machine" /><h2>Machine Information</h2>');
1.46      albertel  227:     &log($fh,"<h3>loadavg</h3>");
                    228: 	
                    229:     open (LOADAVGH,"/proc/loadavg");
                    230:     my $loadavg=<LOADAVGH>;
                    231:     close (LOADAVGH);
                    232:     
                    233:     &log($fh,"<tt>$loadavg</tt>");
                    234:     
                    235:     my @parts=split(/\s+/,$loadavg);
                    236:     if ($parts[1]>4.0) {
                    237: 	$errors++;
                    238:     } elsif ($parts[1]>2.0) {
                    239: 	$warnings++;
                    240:     } elsif ($parts[1]>1.0) {
                    241: 	$notices++;
                    242:     }
1.13      harris41  243: 
1.46      albertel  244:     &log($fh,"<h3>df</h3>");
                    245:     &log($fh,"<pre>");
1.14      harris41  246: 
1.46      albertel  247:     open (DFH,"df|");
                    248:     while (my $line=<DFH>) { 
1.48      albertel  249: 	&log($fh,&encode_entities($line,'<>&"')); 
1.46      albertel  250: 	@parts=split(/\s+/,$line);
                    251: 	my $usage=$parts[4];
                    252: 	$usage=~s/\W//g;
                    253: 	if ($usage>90) { 
                    254: 	    $warnings++;
                    255: 	    $notices++; 
                    256: 	} elsif ($usage>80) {
                    257: 	    $warnings++;
                    258: 	} elsif ($usage>60) {
                    259: 	    $notices++;
1.31      albertel  260: 	}
1.46      albertel  261: 	if ($usage>95) { $warnings++; $warnings++; $simplestatus{'diskfull'}++; }
1.1       albertel  262:     }
1.46      albertel  263:     close (DFH);
                    264:     &log($fh,"</pre>");
1.1       albertel  265: 
                    266: 
1.46      albertel  267:     &log($fh,"<h3>ps</h3>");
                    268:     &log($fh,"<pre>");
                    269:     my $psproc=0;
1.1       albertel  270: 
1.53      albertel  271:     open (PSH,"ps aux --cols 140 |");
1.46      albertel  272:     while (my $line=<PSH>) { 
1.48      albertel  273: 	&log($fh,&encode_entities($line,'<>&"')); 
1.46      albertel  274: 	$psproc++;
                    275:     }
                    276:     close (PSH);
                    277:     &log($fh,"</pre>");
1.1       albertel  278: 
1.46      albertel  279:     if ($psproc>200) { $notices++; }
                    280:     if ($psproc>250) { $notices++; }
1.1       albertel  281: 
1.61      albertel  282:     &log($fh,"<h3>distprobe</h3>");
                    283:     &log($fh,"<pre>");
1.98      raeburn   284:     &log($fh,&encode_entities(&LONCAPA::distro(),'<>&"'));
1.61      albertel  285:     &log($fh,"</pre>");
                    286: 
1.46      albertel  287:     &errout($fh);
                    288: }
1.1       albertel  289: 
1.46      albertel  290: sub start_logging {
1.43      albertel  291:     my $fh=IO::File->new(">$statusdir/newstatus.html");
                    292:     my %simplestatus=();
1.46      albertel  293:     my $now=time;
                    294:     my $date=localtime($now);
1.43      albertel  295:     
1.46      albertel  296: 
                    297:     &log($fh,(<<ENDHEADERS));
1.101     raeburn   298: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
                    299: <html xmlns="http://www.w3.org/1999/xhtml" xml:lang="en" lang="en">
1.1       albertel  300: <head>
                    301: <title>LON Status Report $perlvar{'lonHostID'}</title>
1.101     raeburn   302: <meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
1.1       albertel  303: </head>
1.3       www       304: <body bgcolor="#AAAAAA">
1.48      albertel  305: <a name="top" />
1.1       albertel  306: <h1>LON Status Report $perlvar{'lonHostID'}</h1>
                    307: <h2>$date ($now)</h2>
                    308: <ol>
1.48      albertel  309: <li><a href="#configuration">Configuration</a></li>
                    310: <li><a href="#machine">Machine Information</a></li>
                    311: <li><a href="#tmp">Temporary Files</a></li>
                    312: <li><a href="#tokens">Session Tokens</a></li>
1.102     raeburn   313: <li><a href="#webdav">WebDAV Session Tokens</a></li>
1.48      albertel  314: <li><a href="#httpd">httpd</a></li>
                    315: <li><a href="#lonsql">lonsql</a></li>
                    316: <li><a href="#lond">lond</a></li>
                    317: <li><a href="#lonc">lonc</a></li>
                    318: <li><a href="#lonnet">lonnet</a></li>
                    319: <li><a href="#connections">Connections</a></li>
                    320: <li><a href="#delayed">Delayed Messages</a></li>
                    321: <li><a href="#errcount">Error Count</a></li>
1.1       albertel  322: </ol>
1.48      albertel  323: <hr />
                    324: <a name="configuration" />
1.1       albertel  325: <h2>Configuration</h2>
                    326: <h3>PerlVars</h3>
1.48      albertel  327: <table border="2">
1.1       albertel  328: ENDHEADERS
                    329: 
1.46      albertel  330:     foreach my $varname (sort(keys(%perlvar))) {
1.48      albertel  331: 	&log($fh,"<tr><td>$varname</td><td>".
                    332: 	     &encode_entities($perlvar{$varname},'<>&"')."</td></tr>\n");
1.43      albertel  333:     }
1.48      albertel  334:     &log($fh,"</table><h3>Hosts</h3><table border='2'>");
1.72      albertel  335:     my %hostname = &Apache::lonnet::all_hostnames();
                    336:     foreach my $id (sort(keys(%hostname))) {
                    337: 	my $role = (&Apache::lonnet::is_library($id) ? 'library'
                    338: 		                                     : 'access');
1.46      albertel  339: 	&log($fh,
1.72      albertel  340: 	    "<tr><td>$id</td><td>".&Apache::lonnet::host_domain($id).
                    341: 	    "</td><td>".$role.
                    342: 	    "</td><td>".&Apache::lonnet::hostname($id)."</td></tr>\n");
                    343:     }
1.101     raeburn   344:     &log($fh,"</table><h3>Spare Hosts</h3>");
                    345:     if (keys(%Apache::lonnet::spareid) > 0) {
                    346:         &log($fh,"<ul>");
                    347:         foreach my $type (sort(keys(%Apache::lonnet::spareid))) {
                    348: 	    &log($fh,"<li>$type\n<ol>");
                    349: 	    foreach my $id (@{ $Apache::lonnet::spareid{$type} }) {
                    350: 	        &log($fh,"<li>$id</li>\n");
                    351: 	    }
                    352: 	    &log($fh,"</ol>\n</li>\n");
                    353:         }
                    354:         &log($fh,"</ul>\n");
                    355:     } else {
                    356:         &log($fh,"No spare hosts specified<br />\n");
1.43      albertel  357:     }
1.46      albertel  358:     return $fh;
                    359: }
1.11      www       360: 
                    361: # --------------------------------------------------------------- clean out tmp
1.46      albertel  362: sub clean_tmp {
                    363:     my ($fh)=@_;
1.48      albertel  364:     &log($fh,'<hr /><a name="tmp" /><h2>Temporary Files</h2>');
1.82      raeburn   365:     my ($cleaned,$old,$removed) = (0,0,0);
                    366:     my %errors = (
                    367:                      dir       => [],
                    368:                      file      => [],
                    369:                      failopen  => [],
                    370:                  );
                    371:     my %error_titles = (
                    372:                          dir       => 'failed to remove empty directory:',
                    373:                          file      => 'failed to unlike stale file',
                    374:                          failopen  => 'failed to open file or directory'
                    375:                        );
                    376:     ($cleaned,$old,$removed) = &recursive_clean_tmp('',$cleaned,$old,$removed,\%errors);
                    377:     &log($fh,"Cleaned up: ".$cleaned." files; removed: $removed empty directories; (found: $old old checkout tokens)");
                    378:     foreach my $key (sort(keys(%errors))) {
                    379:         if (ref($errors{$key}) eq 'ARRAY') {
                    380:             if (@{$errors{$key}} > 0) {
                    381:                 &log($fh,"Error during cleanup ($error_titles{$key}):<ul><li>".
                    382:                      join('</li><li><tt>',@{$errors{$key}}).'</tt></li></ul><br />');
                    383:             }
                    384:         }
                    385:     }
                    386: }
                    387: 
                    388: sub recursive_clean_tmp {
                    389:     my ($subdir,$cleaned,$old,$removed,$errors) = @_;
                    390:     my $base = "$perlvar{'lonDaemons'}/tmp";
                    391:     my $path = $base;
                    392:     next if ($subdir =~ m{\.\./});
                    393:     next unless (ref($errors) eq 'HASH');
                    394:     unless ($subdir eq '') {
                    395:         $path .= '/'.$subdir;
                    396:     }
                    397:     if (opendir(my $dh,"$path")) {
                    398:         while (my $file = readdir($dh)) {
                    399:             next if ($file =~ /^\.\.?$/);
                    400:             my $fname = "$path/$file";
                    401:             if (-d $fname) {
                    402:                 my $innerdir;
                    403:                 if ($subdir eq '') {
                    404:                     $innerdir = $file;
                    405:                 } else {
                    406:                     $innerdir = $subdir.'/'.$file;
                    407:                 }
                    408:                 ($cleaned,$old,$removed) = 
                    409:                      &recursive_clean_tmp($innerdir,$cleaned,$old,$removed,$errors);
                    410:                 my @doms = &Apache::lonnet::current_machine_domains();
                    411:                 
                    412:                 if (open(my $dirhandle,$fname)) {
                    413:                     unless (($innerdir eq 'helprequests') ||
                    414:                             (($innerdir =~ /^addcourse/) && ($innerdir !~ m{/\d+$}))) {
                    415:                         my @contents = grep {!/^\.\.?$/} readdir($dirhandle);
                    416:                                       join('&&',@contents)."\n";    
                    417:                         if (scalar(grep {!/^\.\.?$/} readdir($dirhandle)) == 0) {
                    418:                             closedir($dirhandle);
                    419:                             if ($fname =~ m{^\Q$perlvar{'lonDaemons'}\E/tmp/}) {
                    420:                                 if (rmdir($fname)) {
                    421:                                     $removed ++;
                    422:                                 } elsif (ref($errors->{dir}) eq 'ARRAY') {
                    423:                                     push(@{$errors->{dir}},$fname);
                    424:                                 }
                    425:                             }
                    426:                         }
                    427:                     } else {
                    428:                         closedir($dirhandle);
                    429:                     }
                    430:                 }
                    431:             } else {
                    432:                 my ($dev,$ino,$mode,$nlink,
                    433:                     $uid,$gid,$rdev,$size,
                    434:                     $atime,$mtime,$ctime,
                    435:                     $blksize,$blocks)=stat($fname);
                    436:                 my $now=time;
                    437:                 my $since=$now-$mtime;
                    438:                 if ($since>$perlvar{'lonExpire'}) {
                    439:                     if ($subdir eq '') {
                    440:                         my $line='';
                    441:                         if ($fname =~ /\.db$/) {
                    442:                             if (unlink($fname)) {
                    443:                                 $cleaned++;
                    444:                             } elsif (ref($errors->{file}) eq 'ARRAY') {
                    445:                                 push(@{$errors->{file}},$fname);
                    446:                             }
                    447:                         } elsif (open(PROBE,$fname)) {
                    448:                             my $line='';
                    449:                             $line=<PROBE>;
                    450:                             close(PROBE);
                    451:                             if ($line=~/^CHECKOUTTOKEN\&/) {
                    452:                                 if ($since>365*$perlvar{'lonExpire'}) {
                    453:                                     if (unlink($fname)) {
                    454:                                         $cleaned++; 
                    455:                                     } elsif (ref($errors->{file}) eq 'ARRAY') {
                    456:                                         push(@{$errors->{file}},$fname);
                    457:                                     }
                    458:                                 } else {
                    459:                                     $old++;
                    460:                                 }
                    461:                             } else {
                    462:                                 if (unlink($fname)) {
                    463:                                     $cleaned++;
                    464:                                 } elsif (ref($errors->{file}) eq 'ARRAY') {
                    465:                                     push(@{$errors->{file}},$fname);
                    466:                                 }
                    467:                             }
                    468:                         } elsif (ref($errors->{failopen}) eq 'ARRAY') {
                    469:                             push(@{$errors->{failopen}},$fname); 
                    470:                         }
                    471:                     } else {
                    472:                         if (unlink($fname)) {
                    473:                             $cleaned++;
                    474:                         } elsif (ref($errors->{file}) eq 'ARRAY') {
                    475:                             push(@{$errors->{file}},$fname);
                    476:                         }
                    477:                     }
                    478:                 }
                    479:             }
                    480:         }
                    481:         closedir($dh);
                    482:     } elsif (ref($errors->{failopen}) eq 'ARRAY') {
                    483:         push(@{$errors->{failopen}},$path);
1.43      albertel  484:     }
1.82      raeburn   485:     return ($cleaned,$old,$removed);
1.46      albertel  486: }
1.11      www       487: 
                    488: # ------------------------------------------------------------ clean out lonIDs
1.46      albertel  489: sub clean_lonIDs {
                    490:     my ($fh)=@_;
1.48      albertel  491:     &log($fh,'<hr /><a name="tokens" /><h2>Session Tokens</h2>');
1.46      albertel  492:     my $cleaned=0;
                    493:     my $active=0;
                    494:     while (my $fname=<$perlvar{'lonIDsDir'}/*>) {
1.43      albertel  495: 	my ($dev,$ino,$mode,$nlink,
                    496: 	    $uid,$gid,$rdev,$size,
                    497: 	    $atime,$mtime,$ctime,
                    498: 	    $blksize,$blocks)=stat($fname);
1.46      albertel  499: 	my $now=time;
                    500: 	my $since=$now-$mtime;
1.43      albertel  501: 	if ($since>$perlvar{'lonExpire'}) {
                    502: 	    $cleaned++;
1.101     raeburn   503: 	    &log($fh,"Unlinking $fname<br />");
1.43      albertel  504: 	    unlink("$fname");
                    505: 	} else {
                    506: 	    $active++;
                    507: 	}
1.46      albertel  508:     }
1.48      albertel  509:     &log($fh,"<p>Cleaned up ".$cleaned." stale session token(s).</p>");
1.46      albertel  510:     &log($fh,"<h3>$active open session(s)</h3>");
                    511: }
1.43      albertel  512: 
1.102     raeburn   513: # ------------------------------------------------ clean out webDAV Session IDs
                    514: sub clean_webDAV_sessionIDs {
                    515:     my ($fh)=@_;
                    516:     if ($perlvar{'lonRole'} eq 'library') {
                    517:         &log($fh,'<hr /><a name="webdav" /><h2>WebDAV Session Tokens</h2>');
                    518:         my $cleaned=0;
                    519:         my $active=0;
                    520:         my $now = time;
                    521:         if (-d $perlvar{'lonDAVsessDir'}) {
                    522:             while (my $fname=<$perlvar{'lonDAVsessDir'}/*>) {
                    523:                 my @stats = stat($fname);
                    524:                 my $since=$now-$stats[9];
                    525:                 if ($since>$perlvar{'lonExpire'}) {
                    526:                     $cleaned++;
                    527:                     &log($fh,"Unlinking $fname<br />");
                    528:                     unlink("$fname");
                    529:                 } else {
                    530:                     $active++;
                    531:                 }
                    532:             }
                    533:             &log($fh,"<p>Cleaned up ".$cleaned." stale webDAV session token(s).</p>");
                    534:             &log($fh,"<h3>$active open webDAV session(s)</h3>");
                    535:         }
                    536:     }
                    537: }
                    538: 
1.74      albertel  539: # ----------------------------------------------------------- clean out sockets
                    540: sub clean_sockets {
                    541:     my ($fh)=@_;
                    542:     my $cleaned=0;
                    543:     opendir(SOCKETS,$perlvar{'lonSockDir'});
                    544:     while (my $fname=readdir(SOCKETS)) {
                    545: 	next if (-d $fname 
1.80      www       546: 		 || $fname=~/(mysqlsock|maximasock|rsock|\Q$perlvar{'lonSockDir'}\E)/);
1.74      albertel  547: 	$cleaned++;
                    548: 	&log($fh,"Unlinking $fname<br />");
                    549: 	unlink("/home/httpd/sockets/$fname");
                    550:     }
                    551:     &log($fh,"<p>Cleaned up ".$cleaned." stale sockets.</p>");
                    552: }
                    553: 
1.11      www       554: 
1.1       albertel  555: # ----------------------------------------------------------------------- httpd
1.46      albertel  556: sub check_httpd_logs {
                    557:     my ($fh)=@_;
1.94      raeburn   558:     if (open(PIPE,"./lchttpdlogs|")) {
1.93      raeburn   559:         while (my $line=<PIPE>) {
                    560:             &log($fh,$line);
                    561:             if ($line=~/\[error\]/) { $notices++; }
                    562:         }
                    563:         close(PIPE);
1.46      albertel  564:     }
1.43      albertel  565:     &errout($fh);
1.46      albertel  566: }
1.1       albertel  567: 
                    568: # ---------------------------------------------------------------------- lonnet
                    569: 
1.48      albertel  570: sub rotate_lonnet_logs {
1.46      albertel  571:     my ($fh)=@_;
1.48      albertel  572:     &log($fh,'<hr /><a name="lonnet" /><h2>lonnet</h2><h3>Temp Log</h3><pre>');
1.100     bisitz    573:     print "Checking logs.\n";
1.43      albertel  574:     if (-e "$perlvar{'lonDaemons'}/logs/lonnet.log"){
                    575: 	open (DFH,"tail -n50 $perlvar{'lonDaemons'}/logs/lonnet.log|");
1.46      albertel  576: 	while (my $line=<DFH>) { 
1.48      albertel  577: 	    &log($fh,&encode_entities($line,'<>&"'));
1.46      albertel  578: 	}
1.43      albertel  579: 	close (DFH);
                    580:     }
1.46      albertel  581:     &log($fh,"</pre><h3>Perm Log</h3><pre>");
1.43      albertel  582:     
                    583:     if (-e "$perlvar{'lonDaemons'}/logs/lonnet.perm.log") {
                    584: 	open(DFH,"tail -n10 $perlvar{'lonDaemons'}/logs/lonnet.perm.log|");
1.46      albertel  585: 	while (my $line=<DFH>) { 
1.48      albertel  586: 	    &log($fh,&encode_entities($line,'<>&"'));
1.46      albertel  587: 	}
1.43      albertel  588: 	close (DFH);
1.46      albertel  589:     } else { &log($fh,"No perm log\n") }
1.43      albertel  590: 
1.46      albertel  591:     my $fname="$perlvar{'lonDaemons'}/logs/lonnet.log";
1.73      albertel  592:     &rotate_logfile($fname,$fh,'lonnet log');
1.1       albertel  593: 
1.46      albertel  594:     &log($fh,"</pre>");
1.43      albertel  595:     &errout($fh);
1.46      albertel  596: }
                    597: 
1.73      albertel  598: sub rotate_other_logs {
                    599:     my ($fh) = @_;
1.83      raeburn   600:     my %logs = (
                    601:                   autoenroll          => 'Auto Enroll log',
                    602:                   autocreate          => 'Create Course log',
                    603:                   searchcat           => 'Search Cataloguing log',
                    604:                   autoupdate          => 'Auto Update log',
                    605:                   refreshcourseids_db => 'Refresh CourseIDs db log',
                    606:                );
                    607:     foreach my $item (keys(%logs)) {
                    608:         my $fname=$perlvar{'lonDaemons'}.'/logs/'.$item.'.log';
                    609:         &rotate_logfile($fname,$fh,$logs{$item});
                    610:     }
1.73      albertel  611: }
                    612: 
1.43      albertel  613: # ----------------------------------------------------------------- Connections
1.46      albertel  614: sub test_connections {
1.72      albertel  615:     my ($fh)=@_;
1.48      albertel  616:     &log($fh,'<hr /><a name="connections" /><h2>Connections</h2>');
1.100     bisitz    617:     print "Testing connections.\n";
1.48      albertel  618:     &log($fh,"<table border='2'>");
1.49      albertel  619:     my ($good,$bad)=(0,0);
1.72      albertel  620:     my %hostname = &Apache::lonnet::all_hostnames();
                    621:     foreach my $tryserver (sort(keys(%hostname))) {
1.43      albertel  622: 	print(".");
1.46      albertel  623: 	my $result;
1.72      albertel  624: 	my $answer=&Apache::lonnet::reply("ping",$tryserver);
1.43      albertel  625: 	if ($answer eq "$tryserver:$perlvar{'lonHostID'}") {
                    626: 	    $result="<b>ok</b>";
1.49      albertel  627: 	    $good++;
1.43      albertel  628: 	} else {
                    629: 	    $result=$answer;
                    630: 	    $warnings++;
1.49      albertel  631: 	    if ($answer eq 'con_lost') {
                    632: 		$bad++;
                    633: 		$warnings++;
1.50      albertel  634: 	    } else {
                    635: 		$good++; #self connection
1.49      albertel  636: 	    }
1.43      albertel  637: 	}
                    638: 	if ($answer =~ /con_lost/) { print(" $tryserver down\n"); }
1.46      albertel  639: 	&log($fh,"<tr><td>$tryserver</td><td>$result</td></tr>\n");
1.1       albertel  640:     }
1.46      albertel  641:     &log($fh,"</table>");
1.49      albertel  642:     print "\n$good good, $bad bad connections\n";
1.43      albertel  643:     &errout($fh);
1.46      albertel  644: }
                    645: 
                    646: 
1.1       albertel  647: # ------------------------------------------------------------ Delayed messages
1.46      albertel  648: sub check_delayed_msg {
1.72      albertel  649:     my ($fh)=@_;
1.48      albertel  650:     &log($fh,'<hr /><a name="delayed" /><h2>Delayed Messages</h2>');
1.100     bisitz    651:     print "Checking buffers.\n";
1.46      albertel  652:     
                    653:     &log($fh,'<h3>Scanning Permanent Log</h3>');
1.1       albertel  654: 
1.46      albertel  655:     my $unsend=0;
1.1       albertel  656: 
1.105     raeburn   657:     my %hostname = &Apache::lonnet::all_hostnames();
                    658:     my $numhosts = scalar(keys(%hostname));
                    659: 
1.46      albertel  660:     my $dfh=IO::File->new("$perlvar{'lonDaemons'}/logs/lonnet.perm.log");
                    661:     while (my $line=<$dfh>) {
                    662: 	my ($time,$sdf,$dserv,$dcmd)=split(/:/,$line);
1.105     raeburn   663:         if ($numhosts) {
                    664:             next unless ($hostname{$dserv});
                    665:         }
1.46      albertel  666: 	if ($sdf eq 'F') { 
                    667: 	    my $local=localtime($time);
1.101     raeburn   668: 	    &log($fh,"<b>Failed: $time, $dserv, $dcmd</b><br />");
1.46      albertel  669: 	    $warnings++;
1.43      albertel  670: 	}
1.46      albertel  671: 	if ($sdf eq 'S') { $unsend--; }
                    672: 	if ($sdf eq 'D') { $unsend++; }
1.1       albertel  673:     }
1.46      albertel  674: 
1.48      albertel  675:     &log($fh,"<p>Total unsend messages: <b>$unsend</b></p>\n");
1.95      raeburn   676:     if ($unsend > 0) {
                    677:         $warnings=$warnings+5*$unsend;
                    678:     }
1.1       albertel  679: 
1.43      albertel  680:     if ($unsend) { $simplestatus{'unsend'}=$unsend; }
1.48      albertel  681:     &log($fh,"<h3>Outgoing Buffer</h3>\n<pre>");
1.68      www       682: # list directory with delayed messages and remember offline servers
                    683:     my %servers=();
1.43      albertel  684:     open (DFH,"ls -lF $perlvar{'lonSockDir'}/delayed|");
1.68      www       685:     while (my $line=<DFH>) {
                    686:         my ($server)=($line=~/\.(\w+)$/);
                    687:         if ($server) { $servers{$server}=1; }
1.48      albertel  688: 	&log($fh,&encode_entities($line,'<>&"'));
1.46      albertel  689:     }
1.48      albertel  690:     &log($fh,"</pre>\n");
1.43      albertel  691:     close (DFH);
1.68      www       692: # pong to all servers that have delayed messages
                    693: # this will trigger a reverse connection, which should flush the buffers
1.95      raeburn   694:     foreach my $tryserver (sort(keys(%servers))) {
                    695:         if ($hostname{$tryserver} || !$numhosts) {
                    696:             my $answer;
                    697:             eval {
                    698:                 local $SIG{ ALRM } = sub { die "TIMEOUT" };
                    699:                 alarm(20);
                    700:                 $answer = &Apache::lonnet::reply("pong",$tryserver);
                    701:                 alarm(0);
                    702:             };
                    703:             if ($@ && $@ =~ m/TIMEOUT/) {
                    704:                 &log($fh,"Attempted pong to $tryserver timed out<br />");
1.100     bisitz    705:                 print "Time out while contacting: $tryserver for pong.\n";
1.95      raeburn   706:             } else {
                    707:                 &log($fh,"Pong to $tryserver: $answer<br />");
                    708:             }
1.91      raeburn   709:         } else {
1.95      raeburn   710:             &log($fh,"$tryserver has delayed messages, but is not part of the cluster -- skipping 'Pong'.<br />");
1.91      raeburn   711:         }
1.68      www       712:     }
1.46      albertel  713: }
1.1       albertel  714: 
1.46      albertel  715: sub finish_logging {
                    716:     my ($fh)=@_;
1.48      albertel  717:     &log($fh,"<a name='errcount' />\n");
1.43      albertel  718:     $totalcount=$notices+4*$warnings+100*$errors;
                    719:     &errout($fh);
1.46      albertel  720:     &log($fh,"<h1>Total Error Count: $totalcount</h1>");
                    721:     my $now=time;
                    722:     my $date=localtime($now);
1.48      albertel  723:     &log($fh,"<hr />$date ($now)</body></html>\n");
1.100     bisitz    724:     print "lon-status webpage updated.\n";
1.43      albertel  725:     $fh->close();
1.46      albertel  726: 
                    727:     if ($errors) { $simplestatus{'errors'}=$errors; }
                    728:     if ($warnings) { $simplestatus{'warnings'}=$warnings; }
                    729:     if ($notices) { $simplestatus{'notices'}=$notices; }
                    730:     $simplestatus{'time'}=time;
1.1       albertel  731: }
                    732: 
1.46      albertel  733: sub log_simplestatus {
1.73      albertel  734:     rename("$statusdir/newstatus.html","$statusdir/index.html");
1.46      albertel  735:     
1.43      albertel  736:     my $sfh=IO::File->new(">$statusdir/loncron_simple.txt");
                    737:     foreach (keys %simplestatus) {
                    738: 	print $sfh $_.'='.$simplestatus{$_}.'&';
                    739:     }
                    740:     print $sfh "\n";
                    741:     $sfh->close();
1.41      www       742: }
1.46      albertel  743: 
1.84      raeburn   744: sub write_loncaparevs {
1.100     bisitz    745:     print "Retrieving LON-CAPA version information.\n";
1.99      raeburn   746:     my %hostname = &Apache::lonnet::all_hostnames();
                    747:     my $output;
                    748:     foreach my $id (sort(keys(%hostname))) {
                    749:         if ($id ne '') {
                    750:             my $loncaparev;
                    751:             eval {
                    752:                 local $SIG{ ALRM } = sub { die "TIMEOUT" };
                    753:                 alarm(10);
                    754:                 $loncaparev =
                    755:                     &Apache::lonnet::get_server_loncaparev('',$id,1,'loncron');
                    756:                 alarm(0);
                    757:             };
                    758:             if ($@ && $@ =~ m/TIMEOUT/) {
1.100     bisitz    759:                 print "Time out while contacting lonHost: $id for version.\n";   
1.99      raeburn   760:             }
                    761:             if ($loncaparev =~ /^[\w.\-]+$/) {
                    762:                 $output .= $id.':'.$loncaparev."\n";
                    763:             }
                    764:         }
                    765:     }
                    766:     if ($output) {
                    767:         if (open(my $fh,">$perlvar{'lonTabDir'}/loncaparevs.tab")) {
                    768:             print $fh $output;
                    769:             close($fh);
                    770:             &Apache::lonnet::load_loncaparevs();
                    771:         }
                    772:     }
                    773:     return;
                    774: }
                    775: 
                    776: sub write_serverhomeIDs {
1.100     bisitz    777:     print "Retrieving LON-CAPA lonHostID information.\n";
1.99      raeburn   778:     my %name_to_host = &Apache::lonnet::all_names();
                    779:     my $output;
                    780:     foreach my $name (sort(keys(%name_to_host))) {
                    781:         if ($name ne '') {
                    782:             if (ref($name_to_host{$name}) eq 'ARRAY') {
                    783:                 my $serverhomeID;
1.90      raeburn   784:                 eval {
                    785:                     local $SIG{ ALRM } = sub { die "TIMEOUT" };
                    786:                     alarm(10);
1.99      raeburn   787:                     $serverhomeID = 
                    788:                         &Apache::lonnet::get_server_homeID($name,1,'loncron');
1.90      raeburn   789:                     alarm(0);
                    790:                 };
                    791:                 if ($@ && $@ =~ m/TIMEOUT/) {
1.99      raeburn   792:                     print "Time out while contacting server: $name\n"; 
1.90      raeburn   793:                 }
1.99      raeburn   794:                 if ($serverhomeID ne '') {
                    795:                     $output .= $name.':'.$serverhomeID."\n";
                    796:                 } else {
                    797:                     $output .= $name.':'.$name_to_host{$name}->[0]."\n";
1.84      raeburn   798:                 }
                    799:             }
                    800:         }
                    801:     }
1.99      raeburn   802:     if ($output) {
                    803:         if (open(my $fh,">$perlvar{'lonTabDir'}/serverhomeIDs.tab")) {
                    804:             print $fh $output;
                    805:             close($fh);
                    806:             &Apache::lonnet::load_serverhomeIDs();
1.85      raeburn   807:         }
                    808:     }
                    809:     return;
                    810: }
                    811: 
1.96      raeburn   812: sub write_checksums {
1.98      raeburn   813:     my $distro = &LONCAPA::distro();
1.96      raeburn   814:     if ($distro) {
                    815:         print "Retrieving file version and checksumming.\n";
1.97      raeburn   816:         my $numchksums = 0;
1.96      raeburn   817:         my ($chksumsref,$versionsref) =
1.97      raeburn   818:             &LONCAPA::Checksumming::get_checksums($distro,$perlvar{'lonDaemons'},
                    819:                                                   $perlvar{'lonLib'},
                    820:                                                   $perlvar{'lonIncludes'},
                    821:                                                   $perlvar{'lonTabDir'});
1.96      raeburn   822:         if (ref($chksumsref) eq 'HASH') {
                    823:             $numchksums = scalar(keys(%{$chksumsref}));
                    824:         }
                    825:         print "File version retrieved and checksumming completed for $numchksums files.\n";
                    826:     } else {
                    827:         print "File version retrieval and checksumming skipped - could not determine Linux distro.\n"; 
                    828:     }
1.97      raeburn   829:     return;
1.96      raeburn   830: }
                    831: 
1.107     raeburn   832: sub clean_nosslverify {
                    833:     my ($fh) = @_;
                    834:     my %unlinked; 
                    835:     if (-d "$perlvar{'lonSockDir'}/nosslverify") {
                    836:         if (opendir(my $dh,"$perlvar{'lonSockDir'}/nosslverify")) {
                    837:             while (my $fname=readdir($dh)) {
                    838:                 next if ($fname =~ /^\.+$/);
                    839:                 if (unlink("/home/httpd/sockets/nosslverify/$fname")) {
                    840:                     &log($fh,"Unlinking $fname<br />");
                    841:                     $unlinked{$fname} = 1;
                    842:                 }
                    843:             }
                    844:             closedir($dh);
                    845:         }
                    846:     }
                    847:     &log($fh,"<p>Removed ".scalar(keys(%unlinked))." nosslverify clients</p>");
                    848:     return %unlinked;
                    849: }
                    850: sub clean_lonc_childpids {
                    851:     my $childpiddir = "$perlvar{'lonDocRoot'}/lon-status/loncchld";
                    852:     if (-d $childpiddir) {
                    853:         if (opendir(my $dh,$childpiddir)) {
                    854:             while (my $fname=readdir($dh)) {
                    855:                 next if ($fname =~ /^\.+$/);
                    856:                 unlink("$childpiddir/$fname");
                    857:             }
                    858:             closedir($dh);
                    859:         }
                    860:     }
                    861: }
                    862: 
1.104     raeburn   863: sub write_connection_config {
1.107     raeburn   864:     my ($isprimary,$domconf,$url,%connectssl,%changes);
1.104     raeburn   865:     my $primaryLibServer = &Apache::lonnet::domain($perlvar{'lonDefDomain'},'primary');
                    866:     if ($primaryLibServer eq $perlvar{'lonHostID'}) {
                    867:         $isprimary = 1;
                    868:     } elsif ($primaryLibServer ne '') {
                    869:         my $protocol = $Apache::lonnet::protocol{$primaryLibServer};
                    870:         my $hostname = &Apache::lonnet::hostname($primaryLibServer);
                    871:         unless ($protocol eq 'https') {
                    872:             $protocol = 'http';
                    873:         }
                    874:         $url = $protocol.'://'.$hostname.'/cgi-bin/listdomconfig.pl';
                    875:     }
                    876:     my $domconf = &get_domain_config($perlvar{'lonDefDomain'},$primaryLibServer,$isprimary,
                    877:                                      $url);
                    878:     if (ref($domconf) eq 'HASH') {
                    879:         if (ref($domconf->{'ssl'}) eq 'HASH') {
                    880:             foreach my $connect ('connto','connfrom') {
                    881:                 if (ref($domconf->{'ssl'}->{$connect}) eq 'HASH') {
                    882:                     my ($sslreq,$sslnoreq,$currsetting);
                    883:                     my %contypes;
                    884:                     foreach my $type ('dom','intdom','other') {
                    885:                         $connectssl{$connect.'_'.$type} = $domconf->{'ssl'}->{$connect}->{$type};
                    886:                     }
                    887:                 }
                    888:             }
                    889:         }
                    890:         if (keys(%connectssl)) {
1.107     raeburn   891:             my %currconf; 
                    892:             if (open(my $fh,'<',"$perlvar{'lonTabDir'}/connectionrules.tab")) {
                    893:                 while (my $line = <$fh>) {
                    894:                     chomp($line);
                    895:                     my ($name,$value) = split(/=/,$line);
                    896:                     if ($value =~ /^(?:no|yes|req)$/) {
                    897:                         if ($name =~ /^conn(to|from)_(dom|intdom|other)$/) {
                    898:                             $currconf{$name} = $value;
                    899:                         }
                    900:                     }
                    901:                 }
                    902:                 close($fh);
                    903:             }
                    904:             if (open(my $fh,'>',"$perlvar{'lonTabDir'}/connectionrules.tab")) {
1.104     raeburn   905:                 my $count = 0;
                    906:                 foreach my $key (sort(keys(%connectssl))) { 
                    907:                     print $fh "$key=$connectssl{$key}\n";
1.107     raeburn   908:                     if (exists($currconf{$key})) {
                    909:                         unless ($currconf{$key} eq $connectssl{$key}) {
                    910:                             $changes{$key} = 1;
                    911:                         }
                    912:                     } else {
                    913:                         $changes{$key} = 1;
                    914:                     }
1.104     raeburn   915:                     $count ++;
                    916:                 }
                    917:                 close($fh);
                    918:                 print "Completed writing SSL options for lonc/lond for $count items.\n";
                    919:             }
                    920:         } else {
                    921:             print "Writing of SSL options skipped - no connection rules in domain configuration.\n";
                    922:         }
                    923:     } else {
                    924:         print "Retrieval of SSL options for lonc/lond skipped - no configuration data available for domain.\n";
                    925:     }
1.107     raeburn   926:     return %changes;
1.104     raeburn   927: }
                    928: 
                    929: sub get_domain_config {
                    930:     my ($dom,$primlibserv,$isprimary,$url) = @_;
                    931:     my %confhash;
                    932:     if ($isprimary) {
                    933:         my $lonusersdir = $perlvar{'lonUsersDir'};
                    934:         my $fname = $lonusersdir.'/'.$dom.'/configuration.db';
                    935:         if (-e $fname) {
                    936:             my $dbref=&LONCAPA::locking_hash_tie($fname,&GDBM_READER());
                    937:             if (ref($dbref) eq 'HASH') {
                    938:                 foreach my $key (sort(keys(%{$dbref}))) {
                    939:                     my $value = $dbref->{$key};
                    940:                     if ($value =~ s/^__FROZEN__//) {
                    941:                         $value = thaw(&LONCAPA::unescape($value));
                    942:                     } else {
                    943:                         $value = &LONCAPA::unescape($value);
                    944:                     }
                    945:                     $confhash{$key} = $value;
                    946:                 }
                    947:                 &LONCAPA::locking_hash_untie($dbref);
                    948:             }
                    949:         }
                    950:     } else {
                    951:         if (open(PIPE,"wget --no-check-certificate '$url?primary=$primlibserv&format=raw' |")) {
                    952:             my $config = '';
                    953:             while (<PIPE>) {
                    954:                 $config .= $_;
                    955:             }
                    956:             close(PIPE);
                    957:             if ($config) {
                    958:                 my @pairs=split(/\&/,$config);
                    959:                 foreach my $item (@pairs) {
                    960:                     my ($key,$value)=split(/=/,$item,2);
                    961:                     my $what = &LONCAPA::unescape($key);
                    962:                     if ($value =~ s/^__FROZEN__//) {
                    963:                         $value = thaw(&LONCAPA::unescape($value));
                    964:                     } else {
                    965:                         $value = &LONCAPA::unescape($value);
                    966:                     }
                    967:                     $confhash{$what}=$value;
                    968:                 }
                    969:             }
                    970:         }
                    971:     }
                    972:     return \%confhash;
                    973: }
                    974: 
                    975: sub write_hosttypes {
                    976:     my %intdom = &Apache::lonnet::all_host_intdom();
                    977:     my %hostdom = &Apache::lonnet::all_host_domain();
                    978:     my $dom = $hostdom{$perlvar{'lonHostID'}};
                    979:     my $internetdom = $intdom{$perlvar{'lonHostID'}};
1.107     raeburn   980:     my %changes;
1.104     raeburn   981:     if (($dom ne '') && ($internetdom ne '')) {
                    982:         if (keys(%hostdom)) {
1.107     raeburn   983:             my %currhosttypes;
                    984:             if (open(my $fh,'<',"$perlvar{'lonTabDir'}/hosttypes.tab")) {
                    985:                 while (my $line = <$fh>) {
                    986:                     chomp($line);
                    987:                     my ($name,$value) = split(/:/,$line);
                    988:                     if (($name ne '') && ($value =~ /^(dom|intdom|other)$/)) {
                    989:                         $currhosttypes{$name} = $value;
                    990:                     }
                    991:                 }
                    992:                 close($fh);
                    993:             }
                    994:             if (open(my $fh,'>',"$perlvar{'lonTabDir'}/hosttypes.tab")) {
1.104     raeburn   995:                 my $count = 0;
                    996:                 foreach my $lonid (sort(keys(%hostdom))) {
                    997:                     my $type = 'other';
                    998:                     if ($hostdom{$lonid} eq $dom) {
                    999:                         $type = 'dom'; 
                   1000:                     } elsif ($intdom{$lonid} eq $internetdom) {
                   1001:                         $type = 'intdom';
                   1002:                     }
                   1003:                     print $fh "$lonid:$type\n";
1.107     raeburn  1004:                     if (exists($currhosttypes{$lonid})) {
                   1005:                         if ($type ne $currhosttypes{$lonid}) {
                   1006:                             $changes{$lonid} = 1;
                   1007:                         }
                   1008:                     } else {
                   1009:                         $changes{$lonid} = 1;
                   1010:                     }
1.104     raeburn  1011:                     $count ++;
                   1012:                 }
                   1013:                 close($fh);
                   1014:                 print "Completed writing host type data for $count hosts.\n";
                   1015:             }
                   1016:         } else {
                   1017:             print "Writing of host types skipped - no hosts found.\n";
                   1018:         }
                   1019:     } else {
                   1020:         print "Writing of host types skipped - could not determine this host's LON-CAPA domain or 'internet' domain.\n";
                   1021:     }
1.107     raeburn  1022:     return %changes;
1.104     raeburn  1023: }
                   1024: 
1.106     raeburn  1025: sub update_revocation_list {
1.107     raeburn  1026:     my ($result,$changed) = &Apache::lonnet::fetch_crl_pemfile();
                   1027:     if ($result eq 'ok') {
1.106     raeburn  1028:         print "Certificate Revocation List (from CA) updated.\n";
                   1029:     } else {
                   1030:         print "Certificate Revocation List from (CA) not updated.\n";
                   1031:     }
1.107     raeburn  1032:     return $changed;
                   1033: }
                   1034: 
                   1035: sub reset_nosslverify_pids {
1.108     raeburn  1036:     my ($fh,%sslrem) = @_;
1.107     raeburn  1037:     &checkon_daemon($fh,'lond',40000,'USR2');
                   1038:     my $loncpidfile="$perlvar{'lonDaemons'}/logs/lonc.pid";
                   1039:     my $loncppid;
                   1040:     if ((-e $loncpidfile) && (open(my $pfh,'<',$loncpidfile))) {
                   1041:         $loncppid=<$pfh>;
                   1042:         chomp($loncppid);
                   1043:         close($pfh);
                   1044:         if ($loncppid =~ /^\d+$/) {
                   1045:             my %pids_by_host;
                   1046:             my $docdir = $perlvar{'lonDocRoot'};
                   1047:             if (-d "$docdir/lon-status/loncchld") {
                   1048:                 if (opendir(my $dh,"$docdir/lon-status/loncchld")) {
                   1049:                     while (my $file = readdir($dh)) {
                   1050:                         next if ($file =~ /^\./);
                   1051:                         if (open(my $fh,'<',"$docdir/lon-status/loncchld/$file")) {
                   1052:                             my $record = <$fh>;
                   1053:                             chomp($record);
                   1054:                             close($fh);
                   1055:                             my ($remotehost,$authmode) = split(/:/,$record);
                   1056:                             $pids_by_host{$remotehost}{$authmode}{$file} = 1;
                   1057:                         }
                   1058:                     }
                   1059:                     closedir($dh);
                   1060:                     if (keys(%pids_by_host)) {
                   1061:                         foreach my $host (keys(%pids_by_host)) {
                   1062:                             if ($sslrem{$host}) {
                   1063:                                 if (ref($pids_by_host{$host}) eq 'HASH') {
                   1064:                                     if (ref($pids_by_host{$host}{'insecure'}) eq 'HASH') {
1.109     raeburn  1065:                                         if (keys(%{$pids_by_host{$host}{'insecure'}})) {
                   1066:                                             foreach my $pid (keys(%{$pids_by_host{$host}{'insecure'}})) {
1.107     raeburn  1067:                                                 if (open(PIPE,"ps -o ppid= -p $pid |")) {
                   1068:                                                     my $ppid = <PIPE>;
                   1069:                                                     chomp($ppid);
                   1070:                                                     close(PIPE);
                   1071:                                                     $ppid =~ s/(^\s+|\s+$)//g;
                   1072:                                                     if (($ppid == $loncppid) && (kill 0 => $pid)) {
                   1073:                                                         kill QUIT => $pid;
                   1074:                                                     }
                   1075:                                                 }
                   1076:                                             }
                   1077:                                         }
                   1078:                                     }
                   1079:                                 }
                   1080:                             }
                   1081:                         }
                   1082:                     }
                   1083:                 }
                   1084:             }
                   1085:         }
                   1086:     }
                   1087:     return;
1.106     raeburn  1088: }
                   1089: 
1.46      albertel 1090: sub send_mail {
1.79      raeburn  1091:     my $defdom = $perlvar{'lonDefDomain'};
                   1092:     my $origmail = $perlvar{'lonAdmEMail'};
1.78      raeburn  1093:     my $emailto = &Apache::loncommon::build_recipient_list(undef,
                   1094:                                    'lonstatusmail',$defdom,$origmail);
1.54      www      1095:     if ($totalcount>2500) {
1.43      albertel 1096: 	$emailto.=",$perlvar{'lonSysEMail'}";
                   1097:     }
1.101     raeburn  1098:     my $from;
                   1099:     my $hostname=`/bin/hostname`;
                   1100:     chop($hostname);
                   1101:     $hostname=~s/[^\w\.]//g;
                   1102:     if ($hostname) {
                   1103:         $from = 'www@'.$hostname;
                   1104:     }
                   1105:     my $subj="LON: $perlvar{'lonHostID'} E:$errors W:$warnings N:$notices";
                   1106:     my $loncronmail = "To: $emailto\n".
                   1107:                       "From: $from\n".
                   1108:                       "Subject: ".$subj."\n".
                   1109:                       "Content-type: text/html\; charset=UTF-8\n".
                   1110:                       "MIME-Version: 1.0\n\n";
                   1111:     if (open(my $fh,"<$statusdir/index.html")) {
                   1112:         while (<$fh>) {
                   1113:             $loncronmail .= $_;
                   1114:         }
                   1115:         close($fh);
                   1116:     } else {
                   1117:         $loncronmail .= "Failed to read from http://$hostname/lon-status/index.html\n";
                   1118:     }
                   1119:     $loncronmail .= "\n\n";
                   1120:     if (open(my $mailh, "|/usr/lib/sendmail -oi -t -odb")) {
                   1121:         print $mailh $loncronmail;
                   1122:         close($mailh);
                   1123:         print "Sending mail.\n";
                   1124:     } else {
                   1125:         print "Sending mail failed.\n";
1.52      albertel 1126:     }
1.1       albertel 1127: }
1.46      albertel 1128: 
1.49      albertel 1129: sub usage {
                   1130:     print(<<USAGE);
1.100     bisitz   1131: loncron - housekeeping program that checks up on various parts of LON-CAPA
1.49      albertel 1132: 
                   1133: Options:
1.71      albertel 1134:    --help     Display 
1.49      albertel 1135:    --noemail  Do not send the status email
                   1136:    --justcheckconnections  Only check the current status of the lonc/d
                   1137:                                 connections, do not send emails do not
                   1138:                                 check if the daemons are running, do not
                   1139:                                 generate lon-status
                   1140:    --justcheckdaemons      Only check that all of the Lon-CAPA daemons are
                   1141:                                 running, do not send emails do not
                   1142:                                 check the lonc/d connections, do not
                   1143:                                 generate lon-status
1.59      albertel 1144:    --justreload            Only tell the daemons to reload the config files,
                   1145: 				do not send emails do not
                   1146:                                 check if the daemons are running, do not
                   1147:                                 generate lon-status
1.49      albertel 1148:                            
                   1149: USAGE
                   1150: }
                   1151: 
1.46      albertel 1152: # ================================================================ Main Program
                   1153: sub main () {
1.71      albertel 1154:     my ($help,$justcheckdaemons,$noemail,$justcheckconnections,
1.59      albertel 1155: 	$justreload);
1.49      albertel 1156:     &GetOptions("help"                 => \$help,
                   1157: 		"justcheckdaemons"     => \$justcheckdaemons,
                   1158: 		"noemail"              => \$noemail,
1.59      albertel 1159: 		"justcheckconnections" => \$justcheckconnections,
                   1160: 		"justreload"           => \$justreload
1.49      albertel 1161: 		);
                   1162:     if ($help) { &usage(); return; }
1.46      albertel 1163: # --------------------------------- Read loncapa_apache.conf and loncapa.conf
                   1164:     my $perlvarref=LONCAPA::Configuration::read_conf('loncapa.conf');
                   1165:     %perlvar=%{$perlvarref};
                   1166:     undef $perlvarref;
                   1167:     delete $perlvar{'lonReceipt'}; # remove since sensitive and not needed
                   1168:     delete $perlvar{'lonSqlAccess'}; # remove since sensitive and not needed
1.75      albertel 1169:     chdir($perlvar{'lonDaemons'});
1.46      albertel 1170: # --------------------------------------- Make sure that LON-CAPA is configured
                   1171: # I only test for one thing here (lonHostID).  This is just a safeguard.
                   1172:     if ('{[[[[lonHostID]]]]}' eq $perlvar{'lonHostID'}) {
                   1173: 	print("Unconfigured machine.\n");
                   1174: 	my $emailto=$perlvar{'lonSysEMail'};
                   1175: 	my $hostname=`/bin/hostname`;
                   1176: 	chop $hostname;
                   1177: 	$hostname=~s/[^\w\.]//g; # make sure is safe to pass through shell
                   1178: 	my $subj="LON: Unconfigured machine $hostname";
                   1179: 	system("echo 'Unconfigured machine $hostname.' |\
                   1180:  mailto $emailto -s '$subj' > /dev/null");
                   1181: 	exit 1;
                   1182:     }
                   1183: 
                   1184: # ----------------------------- Make sure this process is running from user=www
                   1185:     my $wwwid=getpwnam('www');
                   1186:     if ($wwwid!=$<) {
1.100     bisitz   1187: 	print("User ID mismatch. This program must be run as user 'www'.\n");
1.46      albertel 1188: 	my $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}";
                   1189: 	my $subj="LON: $perlvar{'lonHostID'} User ID mismatch";
1.100     bisitz   1190: 	system("echo 'User ID mismatch. loncron must be run as user www.' |\
1.46      albertel 1191:  mailto $emailto -s '$subj' > /dev/null");
                   1192: 	exit 1;
                   1193:     }
                   1194: 
1.72      albertel 1195: # -------------------------------------------- Force reload of host information
1.103     raeburn  1196:     my $nomemcache;
                   1197:     if ($justcheckdaemons) {
                   1198:         $nomemcache=1;
                   1199:         my $memcachepidfile="$perlvar{'lonDaemons'}/logs/memcached.pid";
                   1200:         my $memcachepid;
                   1201:         if (-e $memcachepidfile) {
                   1202:             my $memfh=IO::File->new($memcachepidfile);
                   1203:             $memcachepid=<$memfh>;
                   1204:             chomp($memcachepid);
                   1205:             if ($memcachepid =~ /^\d+$/ && kill 0 => $memcachepid) {
                   1206:                 undef($nomemcache);
                   1207:             }
                   1208:         }
                   1209:     }
                   1210:     &Apache::lonnet::load_hosts_tab(1,$nomemcache);
                   1211:     &Apache::lonnet::load_domain_tab(1,$nomemcache);
                   1212:     &Apache::lonnet::get_iphost(1,$nomemcache);
1.46      albertel 1213: 
1.81      raeburn  1214: # ----------------------------------------- Force firewall update for lond port  
                   1215: 
                   1216:     if ((!$justcheckdaemons) && (!$justreload)) {
                   1217:         my $now = time;
                   1218:         my $tmpfile = $perlvar{'lonDaemons'}.'/tmp/lciptables_iphost_'.
                   1219:                       $now.$$.int(rand(10000));
                   1220:         if (open(my $fh,">$tmpfile")) {
                   1221:             my %iphosts = &Apache::lonnet::get_iphost();
                   1222:             foreach my $key (keys(%iphosts)) {
                   1223:                 print $fh "$key\n";
                   1224:             }
                   1225:             close($fh);
1.89      raeburn  1226:             if (&LONCAPA::try_to_lock('/tmp/lock_lciptables')) {
                   1227:                 my $execpath = $perlvar{'lonDaemons'}.'/lciptables';
                   1228:                 system("$execpath $tmpfile");
                   1229:                 unlink('/tmp/lock_lciptables');  # Remove the lock file. 
                   1230:             }
1.88      raeburn  1231:             unlink($tmpfile);
1.81      raeburn  1232:         }
                   1233:     }
                   1234: 
1.46      albertel 1235: # ---------------------------------------------------------------- Start report
                   1236: 
                   1237:     $errors=0;
                   1238:     $warnings=0;
                   1239:     $notices=0;
                   1240: 
                   1241: 	
1.49      albertel 1242:     my $fh;
1.59      albertel 1243:     if (!$justcheckdaemons && !$justcheckconnections && !$justreload) {
1.72      albertel 1244: 	$fh=&start_logging();
1.49      albertel 1245: 
                   1246: 	&log_machine_info($fh);
                   1247: 	&clean_tmp($fh);
                   1248: 	&clean_lonIDs($fh);
1.102     raeburn  1249:         &clean_webDAV_sessionIDs($fh);
1.49      albertel 1250: 	&check_httpd_logs($fh);
                   1251: 	&rotate_lonnet_logs($fh);
1.73      albertel 1252: 	&rotate_other_logs($fh);
1.49      albertel 1253:     }
1.59      albertel 1254:     if (!$justcheckconnections && !$justreload) {
1.76      albertel 1255: 	&checkon_daemon($fh,'lonmemcached',40000);
1.49      albertel 1256: 	&checkon_daemon($fh,'lonsql',200000);
1.63      albertel 1257: 	if ( &checkon_daemon($fh,'lond',40000,'USR1') eq 'running') {
                   1258: 	    &checkon_daemon($fh,'lond',40000,'USR2');
                   1259: 	}
1.71      albertel 1260: 	&checkon_daemon($fh,'lonc',40000,'USR1');
1.70      raeburn  1261:         &checkon_daemon($fh,'lonmaxima',40000);
1.80      www      1262:         &checkon_daemon($fh,'lonr',40000);
1.49      albertel 1263:     }
1.59      albertel 1264:     if ($justreload) {
1.107     raeburn  1265:         &clean_nosslverify($fh);
1.104     raeburn  1266:         &write_connection_config();
                   1267:         &write_hosttypes();
1.107     raeburn  1268:         &update_revocation_list(); 
1.59      albertel 1269: 	&checkon_daemon($fh,'lond',40000,'USR2');
1.71      albertel 1270: 	&checkon_daemon($fh,'lonc',40000,'USR2');
1.59      albertel 1271:     }
1.63      albertel 1272:     if ($justcheckconnections) {
1.72      albertel 1273: 	&test_connections($fh);
1.49      albertel 1274:     }
1.59      albertel 1275:     if (!$justcheckdaemons && !$justcheckconnections && !$justreload) {
1.72      albertel 1276: 	&check_delayed_msg($fh);
1.49      albertel 1277: 	&log_simplestatus();
1.87      raeburn  1278:         &write_loncaparevs();
                   1279:         &write_serverhomeIDs();
1.97      raeburn  1280: 	&write_checksums();
1.107     raeburn  1281:         my %sslrem = &clean_nosslverify($fh);
                   1282:         my %conchgs = &write_connection_config();
                   1283:         my %hosttypechgs = &write_hosttypes();
                   1284:         my $hadcrlchg = &update_revocation_list();
1.108     raeburn  1285:         if ((keys(%conchgs) > 0) || (keys(%hosttypechgs) > 0) ||
1.107     raeburn  1286:             $hadcrlchg || (keys(%sslrem) > 0)) {
                   1287:             &checkon_daemon($fh,'lond',40000,'USR2');
1.108     raeburn  1288:             &reset_nosslverify_pids($fh,%sslrem);
1.107     raeburn  1289:         }
1.108     raeburn  1290:         &finish_logging($fh);
1.49      albertel 1291: 	if ($totalcount>200 && !$noemail) { &send_mail(); }
                   1292:     }
1.46      albertel 1293: }
                   1294: 
                   1295: &main();
1.1       albertel 1296: 1;
                   1297: 

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>
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.