--- loncom/loncron 2009/02/11 15:19:57 1.78 +++ loncom/loncron 2018/10/29 02:57:30 1.112 @@ -2,7 +2,7 @@ # Housekeeping program, started by cron, loncontrol and loncron.pl # -# $Id: loncron,v 1.78 2009/02/11 15:19:57 raeburn Exp $ +# $Id: loncron,v 1.112 2018/10/29 02:57:30 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -32,12 +32,17 @@ use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA::Configuration; +use LONCAPA::Checksumming; +use LONCAPA; use Apache::lonnet; +use Apache::loncommon; use IO::File; use IO::Socket; use HTML::Entities; use Getopt::Long; +use GDBM_File; +use Storable qw(thaw); #globals use vars qw (%perlvar %simplestatus $errors $warnings $notices $totalcount); @@ -108,17 +113,20 @@ sub checkon_daemon { my $result; &log($fh,'

'.$daemon.'

Log

'); printf("%-15s ",$daemon); - if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){ - open (DFH,"tail -n25 $perlvar{'lonDaemons'}/logs/$daemon.log|"); - while (my $line=) { - &log($fh,"$line"); - if ($line=~/INFO/) { $notices++; } - if ($line=~/WARNING/) { $notices++; } - if ($line=~/CRITICAL/) { $warnings++; } - }; - close (DFH); + if ($fh) { + if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){ + if (open(DFH,"tail -n25 $perlvar{'lonDaemons'}/logs/$daemon.log|")) { + while (my $line=) { + &log($fh,"$line"); + if ($line=~/INFO/) { $notices++; } + if ($line=~/WARNING/) { $notices++; } + if ($line=~/CRITICAL/) { $warnings++; } + } + close (DFH); + } + } + &log($fh,"

"); } - &log($fh,"

"); my $pidfile="$perlvar{'lonDaemons'}/logs/$daemon.pid"; @@ -154,14 +162,17 @@ sub checkon_daemon { $errors++; my $kadaemon=$daemon; if ($kadaemon eq 'lonmemcached') { $kadaemon='memcached'; } - &log($fh,'
Killall '.$daemon.': '. + &log($fh,'
Killall '.$daemon.': '. `killall $kadaemon 2>&1`.' - '); sleep 1; &log($fh,unlink($pidfile).' - '. `killall -9 $kadaemon 2>&1`. - '
'); + '

'); + if ($kadaemon eq 'loncnew') { + &clean_lonc_childpids(); + } &log($fh,"

$daemon not running, trying to start

"); - + if (&start_daemon($fh,$daemon,$pidfile,$args)) { &log($fh,"

$daemon at pid $daemonpid responding

"); $simplestatus{$daemon}='restarted'; @@ -186,17 +197,19 @@ sub checkon_daemon { &log($fh,"

Unable to start $daemon

"); } } - - if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){ - &log($fh,"

");
-	    open (DFH,"tail -n100 $perlvar{'lonDaemons'}/logs/$daemon.log|");
-	    while (my $line=) { 
-		&log($fh,"$line");
-		if ($line=~/WARNING/) { $notices++; }
-		if ($line=~/CRITICAL/) { $notices++; }
-	    };
-	    close (DFH);
-	    &log($fh,"

"); + if ($fh) { + if (-e "$perlvar{'lonDaemons'}/logs/$daemon.log"){ + &log($fh,"

");
+	        if (open(DFH,"tail -n100 $perlvar{'lonDaemons'}/logs/$daemon.log|")) {
+	            while (my $line=) { 
+		        &log($fh,"$line");
+		        if ($line=~/WARNING/) { $notices++; }
+		        if ($line=~/CRITICAL/) { $notices++; }
+	            }
+	            close (DFH);
+                }
+	        &log($fh,"

"); + } } } @@ -268,12 +281,7 @@ sub log_machine_info { &log($fh,"

distprobe

"); &log($fh,"
");
-    open(DSH,"$perlvar{'lonDaemons'}/distprobe |");
-    while (my $line=) { 
-	&log($fh,&encode_entities($line,'<>&"')); 
-	$psproc++;
-    }
-    close(DSH);
+    &log($fh,&encode_entities(&LONCAPA::distro(),'<>&"'));
     &log($fh,"
"); &errout($fh); @@ -287,9 +295,11 @@ sub start_logging { &log($fh,(< + + LON Status Report $perlvar{'lonHostID'} +
@@ -300,6 +310,7 @@ sub start_logging {
  • Machine Information
  • Temporary Files
  • Session Tokens
  • +
  • WebDAV Session Tokens
  • httpd
  • lonsql
  • lond
  • @@ -330,15 +341,20 @@ ENDHEADERS "".$role. "".&Apache::lonnet::hostname($id)."\n"); } - &log($fh,"

    Spare Hosts

    \n"); return $fh; } @@ -346,33 +362,127 @@ ENDHEADERS sub clean_tmp { my ($fh)=@_; &log($fh,'

    Temporary Files

    '); - my $cleaned=0; - my $old=0; - while (my $fname=<$perlvar{'lonDaemons'}/tmp/*>) { - my ($dev,$ino,$mode,$nlink, - $uid,$gid,$rdev,$size, - $atime,$mtime,$ctime, - $blksize,$blocks)=stat($fname); - my $now=time; - my $since=$now-$mtime; - if ($since>$perlvar{'lonExpire'}) { - my $line=''; - if (open(PROBE,$fname)) { - $line=; - close(PROBE); - } - unless ($line=~/^CHECKOUTTOKEN\&/) { - $cleaned++; - unlink("$fname"); - } else { - if ($since>365*$perlvar{'lonExpire'}) { - $cleaned++; - unlink("$fname"); - } else { $old++; } - } - } + my ($cleaned,$old,$removed) = (0,0,0); + my %errors = ( + dir => [], + file => [], + failopen => [], + ); + my %error_titles = ( + dir => 'failed to remove empty directory:', + file => 'failed to unlike stale file', + failopen => 'failed to open file or directory' + ); + ($cleaned,$old,$removed) = &recursive_clean_tmp('',$cleaned,$old,$removed,\%errors); + &log($fh,"Cleaned up: ".$cleaned." files; removed: $removed empty directories; (found: $old old checkout tokens)"); + foreach my $key (sort(keys(%errors))) { + if (ref($errors{$key}) eq 'ARRAY') { + if (@{$errors{$key}} > 0) { + &log($fh,"Error during cleanup ($error_titles{$key}):
    '); + } + } } - &log($fh,"Cleaned up ".$cleaned." files (".$old." old checkout tokens)."); +} + +sub recursive_clean_tmp { + my ($subdir,$cleaned,$old,$removed,$errors) = @_; + my $base = "$perlvar{'lonDaemons'}/tmp"; + my $path = $base; + next if ($subdir =~ m{\.\./}); + next unless (ref($errors) eq 'HASH'); + unless ($subdir eq '') { + $path .= '/'.$subdir; + } + if (opendir(my $dh,"$path")) { + while (my $file = readdir($dh)) { + next if ($file =~ /^\.\.?$/); + my $fname = "$path/$file"; + if (-d $fname) { + my $innerdir; + if ($subdir eq '') { + $innerdir = $file; + } else { + $innerdir = $subdir.'/'.$file; + } + ($cleaned,$old,$removed) = + &recursive_clean_tmp($innerdir,$cleaned,$old,$removed,$errors); + my @doms = &Apache::lonnet::current_machine_domains(); + + if (open(my $dirhandle,$fname)) { + unless (($innerdir eq 'helprequests') || + (($innerdir =~ /^addcourse/) && ($innerdir !~ m{/\d+$}))) { + my @contents = grep {!/^\.\.?$/} readdir($dirhandle); + join('&&',@contents)."\n"; + if (scalar(grep {!/^\.\.?$/} readdir($dirhandle)) == 0) { + closedir($dirhandle); + if ($fname =~ m{^\Q$perlvar{'lonDaemons'}\E/tmp/}) { + if (rmdir($fname)) { + $removed ++; + } elsif (ref($errors->{dir}) eq 'ARRAY') { + push(@{$errors->{dir}},$fname); + } + } + } + } else { + closedir($dirhandle); + } + } + } else { + my ($dev,$ino,$mode,$nlink, + $uid,$gid,$rdev,$size, + $atime,$mtime,$ctime, + $blksize,$blocks)=stat($fname); + my $now=time; + my $since=$now-$mtime; + if ($since>$perlvar{'lonExpire'}) { + if ($subdir eq '') { + my $line=''; + if ($fname =~ /\.db$/) { + if (unlink($fname)) { + $cleaned++; + } elsif (ref($errors->{file}) eq 'ARRAY') { + push(@{$errors->{file}},$fname); + } + } elsif (open(PROBE,$fname)) { + my $line=''; + $line=; + close(PROBE); + if ($line=~/^CHECKOUTTOKEN\&/) { + if ($since>365*$perlvar{'lonExpire'}) { + if (unlink($fname)) { + $cleaned++; + } elsif (ref($errors->{file}) eq 'ARRAY') { + push(@{$errors->{file}},$fname); + } + } else { + $old++; + } + } else { + if (unlink($fname)) { + $cleaned++; + } elsif (ref($errors->{file}) eq 'ARRAY') { + push(@{$errors->{file}},$fname); + } + } + } elsif (ref($errors->{failopen}) eq 'ARRAY') { + push(@{$errors->{failopen}},$fname); + } + } else { + if (unlink($fname)) { + $cleaned++; + } elsif (ref($errors->{file}) eq 'ARRAY') { + push(@{$errors->{file}},$fname); + } + } + } + } + } + closedir($dh); + } elsif (ref($errors->{failopen}) eq 'ARRAY') { + push(@{$errors->{failopen}},$path); + } + return ($cleaned,$old,$removed); } # ------------------------------------------------------------ clean out lonIDs @@ -390,7 +500,7 @@ sub clean_lonIDs { my $since=$now-$mtime; if ($since>$perlvar{'lonExpire'}) { $cleaned++; - &log($fh,"Unlinking $fname
    "); + &log($fh,"Unlinking $fname
    "); unlink("$fname"); } else { $active++; @@ -400,6 +510,32 @@ sub clean_lonIDs { &log($fh,"

    $active open session(s)

    "); } +# ------------------------------------------------ clean out webDAV Session IDs +sub clean_webDAV_sessionIDs { + my ($fh)=@_; + if ($perlvar{'lonRole'} eq 'library') { + &log($fh,'

    WebDAV Session Tokens

    '); + my $cleaned=0; + my $active=0; + my $now = time; + if (-d $perlvar{'lonDAVsessDir'}) { + while (my $fname=<$perlvar{'lonDAVsessDir'}/*>) { + my @stats = stat($fname); + my $since=$now-$stats[9]; + if ($since>$perlvar{'lonExpire'}) { + $cleaned++; + &log($fh,"Unlinking $fname
    "); + unlink("$fname"); + } else { + $active++; + } + } + &log($fh,"

    Cleaned up ".$cleaned." stale webDAV session token(s).

    "); + &log($fh,"

    $active open webDAV session(s)

    "); + } + } +} + # ----------------------------------------------------------- clean out sockets sub clean_sockets { my ($fh)=@_; @@ -407,7 +543,7 @@ sub clean_sockets { opendir(SOCKETS,$perlvar{'lonSockDir'}); while (my $fname=readdir(SOCKETS)) { next if (-d $fname - || $fname=~/(mysqlsock|maximasock|\Q$perlvar{'lonSockDir'}\E)/); + || $fname=~/(mysqlsock|maximasock|rsock|\Q$perlvar{'lonSockDir'}\E)/); $cleaned++; &log($fh,"Unlinking $fname
    "); unlink("/home/httpd/sockets/$fname"); @@ -419,21 +555,13 @@ sub clean_sockets { # ----------------------------------------------------------------------- httpd sub check_httpd_logs { my ($fh)=@_; - &log($fh,'

    httpd

    Access Log

    ');
    -    
    -    open (DFH,"tail -n25 /etc/httpd/logs/access_log|");
    -    while (my $line=) { &log($fh,&encode_entities($line,'<>&"')) };
    -    close (DFH);
    -	
    -    &log($fh,"

    Error Log

    ");
    -	
    -    open (DFH,"tail -n25 /etc/httpd/logs/error_log|");
    -    while (my $line=) { 
    -	&log($fh,"$line");
    -	if ($line=~/\[error\]/) { $notices++; } 
    +    if (open(PIPE,"./lchttpdlogs|")) {
    +        while (my $line=) {
    +            &log($fh,$line);
    +            if ($line=~/\[error\]/) { $notices++; }
    +        }
    +        close(PIPE);
         }
    -    close (DFH);
    -    &log($fh,"
    "); &errout($fh); } @@ -442,7 +570,7 @@ sub check_httpd_logs { sub rotate_lonnet_logs { my ($fh)=@_; &log($fh,'

    lonnet

    Temp Log

    ');
    -    print "checking logs\n";
    +    print "Checking logs.\n";
         if (-e "$perlvar{'lonDaemons'}/logs/lonnet.log"){
     	open (DFH,"tail -n50 $perlvar{'lonDaemons'}/logs/lonnet.log|");
     	while (my $line=) { 
    @@ -469,19 +597,24 @@ sub rotate_lonnet_logs {
     
     sub rotate_other_logs {
         my ($fh) = @_;
    -    my $fname="$perlvar{'lonDaemons'}/logs/autoenroll.log";
    -    &rotate_logfile($fname,$fh,'Auto Enroll log');
    -    $fname="$perlvar{'lonDaemons'}/logs/autocreate.log";
    -    &rotate_logfile($fname,$fh,'Create Course log');
    -    $fname="$perlvar{'lonDaemons'}/logs/searchcat.log";
    -    &rotate_logfile($fname,$fh,'Search Cataloguing log');
    +    my %logs = (
    +                  autoenroll          => 'Auto Enroll log',
    +                  autocreate          => 'Create Course log',
    +                  searchcat           => 'Search Cataloguing log',
    +                  autoupdate          => 'Auto Update log',
    +                  refreshcourseids_db => 'Refresh CourseIDs db log',
    +               );
    +    foreach my $item (keys(%logs)) {
    +        my $fname=$perlvar{'lonDaemons'}.'/logs/'.$item.'.log';
    +        &rotate_logfile($fname,$fh,$logs{$item});
    +    }
     }
     
     # ----------------------------------------------------------------- Connections
     sub test_connections {
         my ($fh)=@_;
         &log($fh,'

    Connections

    '); - print "testing connections\n"; + print "Testing connections.\n"; &log($fh,""); my ($good,$bad)=(0,0); my %hostname = &Apache::lonnet::all_hostnames(); @@ -515,18 +648,24 @@ sub test_connections { sub check_delayed_msg { my ($fh)=@_; &log($fh,'

    Delayed Messages

    '); - print "checking buffers\n"; + print "Checking buffers.\n"; &log($fh,'

    Scanning Permanent Log

    '); my $unsend=0; + my %hostname = &Apache::lonnet::all_hostnames(); + my $numhosts = scalar(keys(%hostname)); + my $dfh=IO::File->new("$perlvar{'lonDaemons'}/logs/lonnet.perm.log"); while (my $line=<$dfh>) { my ($time,$sdf,$dserv,$dcmd)=split(/:/,$line); + if ($numhosts) { + next unless ($hostname{$dserv}); + } if ($sdf eq 'F') { my $local=localtime($time); - &log($fh,"Failed: $time, $dserv, $dcmd
    "); + &log($fh,"Failed: $time, $dserv, $dcmd
    "); $warnings++; } if ($sdf eq 'S') { $unsend--; } @@ -534,7 +673,9 @@ sub check_delayed_msg { } &log($fh,"

    Total unsend messages: $unsend

    \n"); - $warnings=$warnings+5*$unsend; + if ($unsend > 0) { + $warnings=$warnings+5*$unsend; + } if ($unsend) { $simplestatus{'unsend'}=$unsend; } &log($fh,"

    Outgoing Buffer

    \n
    ");
    @@ -550,9 +691,24 @@ sub check_delayed_msg {
         close (DFH);
     # pong to all servers that have delayed messages
     # this will trigger a reverse connection, which should flush the buffers
    -    foreach my $tryserver (keys %servers) {
    -	my $answer=&Apache::lonnet::reply("pong",$tryserver);
    -	&log($fh,"Pong to $tryserver: $answer
    "); + foreach my $tryserver (sort(keys(%servers))) { + if ($hostname{$tryserver} || !$numhosts) { + my $answer; + eval { + local $SIG{ ALRM } = sub { die "TIMEOUT" }; + alarm(20); + $answer = &Apache::lonnet::reply("pong",$tryserver); + alarm(0); + }; + if ($@ && $@ =~ m/TIMEOUT/) { + &log($fh,"Attempted pong to $tryserver timed out
    "); + print "Time out while contacting: $tryserver for pong.\n"; + } else { + &log($fh,"Pong to $tryserver: $answer
    "); + } + } else { + &log($fh,"$tryserver has delayed messages, but is not part of the cluster -- skipping 'Pong'.
    "); + } } } @@ -565,7 +721,7 @@ sub finish_logging { my $now=time; my $date=localtime($now); &log($fh,"
    $date ($now)\n"); - print "lon-status webpage updated\n"; + print "lon-status webpage updated.\n"; $fh->close(); if ($errors) { $simplestatus{'errors'}=$errors; } @@ -585,26 +741,394 @@ sub log_simplestatus { $sfh->close(); } +sub write_loncaparevs { + print "Retrieving LON-CAPA version information.\n"; + my %hostname = &Apache::lonnet::all_hostnames(); + my $output; + foreach my $id (sort(keys(%hostname))) { + if ($id ne '') { + my $loncaparev; + eval { + local $SIG{ ALRM } = sub { die "TIMEOUT" }; + alarm(10); + $loncaparev = + &Apache::lonnet::get_server_loncaparev('',$id,1,'loncron'); + alarm(0); + }; + if ($@ && $@ =~ m/TIMEOUT/) { + print "Time out while contacting lonHost: $id for version.\n"; + } + if ($loncaparev =~ /^[\w.\-]+$/) { + $output .= $id.':'.$loncaparev."\n"; + } + } + } + if ($output) { + if (open(my $fh,">$perlvar{'lonTabDir'}/loncaparevs.tab")) { + print $fh $output; + close($fh); + &Apache::lonnet::load_loncaparevs(); + } + } + return; +} + +sub write_serverhomeIDs { + print "Retrieving LON-CAPA lonHostID information.\n"; + my %name_to_host = &Apache::lonnet::all_names(); + my $output; + foreach my $name (sort(keys(%name_to_host))) { + if ($name ne '') { + if (ref($name_to_host{$name}) eq 'ARRAY') { + my $serverhomeID; + eval { + local $SIG{ ALRM } = sub { die "TIMEOUT" }; + alarm(10); + $serverhomeID = + &Apache::lonnet::get_server_homeID($name,1,'loncron'); + alarm(0); + }; + if ($@ && $@ =~ m/TIMEOUT/) { + print "Time out while contacting server: $name\n"; + } + if ($serverhomeID ne '') { + $output .= $name.':'.$serverhomeID."\n"; + } else { + $output .= $name.':'.$name_to_host{$name}->[0]."\n"; + } + } + } + } + if ($output) { + if (open(my $fh,">$perlvar{'lonTabDir'}/serverhomeIDs.tab")) { + print $fh $output; + close($fh); + &Apache::lonnet::load_serverhomeIDs(); + } + } + return; +} + +sub write_checksums { + my $distro = &LONCAPA::distro(); + if ($distro) { + print "Retrieving file version and checksumming.\n"; + my $numchksums = 0; + my ($chksumsref,$versionsref) = + &LONCAPA::Checksumming::get_checksums($distro,$perlvar{'lonDaemons'}, + $perlvar{'lonLib'}, + $perlvar{'lonIncludes'}, + $perlvar{'lonTabDir'}); + if (ref($chksumsref) eq 'HASH') { + $numchksums = scalar(keys(%{$chksumsref})); + } + print "File version retrieved and checksumming completed for $numchksums files.\n"; + } else { + print "File version retrieval and checksumming skipped - could not determine Linux distro.\n"; + } + return; +} + +sub clean_nosslverify { + my ($fh) = @_; + my %unlinked; + if (-d "$perlvar{'lonSockDir'}/nosslverify") { + if (opendir(my $dh,"$perlvar{'lonSockDir'}/nosslverify")) { + while (my $fname=readdir($dh)) { + next if ($fname =~ /^\.+$/); + if (unlink("/home/httpd/sockets/nosslverify/$fname")) { + &log($fh,"Unlinking $fname
    "); + $unlinked{$fname} = 1; + } + } + closedir($dh); + } + } + &log($fh,"

    Removed ".scalar(keys(%unlinked))." nosslverify clients

    "); + return %unlinked; +} +sub clean_lonc_childpids { + my $childpiddir = "$perlvar{'lonDocRoot'}/lon-status/loncchld"; + if (-d $childpiddir) { + if (opendir(my $dh,$childpiddir)) { + while (my $fname=readdir($dh)) { + next if ($fname =~ /^\.+$/); + unlink("$childpiddir/$fname"); + } + closedir($dh); + } + } +} + +sub write_connection_config { + my ($isprimary,$domconf,$url,%connectssl,%changes); + my $primaryLibServer = &Apache::lonnet::domain($perlvar{'lonDefDomain'},'primary'); + if ($primaryLibServer eq $perlvar{'lonHostID'}) { + $isprimary = 1; + } elsif ($primaryLibServer ne '') { + my $protocol = $Apache::lonnet::protocol{$primaryLibServer}; + my $hostname = &Apache::lonnet::hostname($primaryLibServer); + unless ($protocol eq 'https') { + $protocol = 'http'; + } + $url = $protocol.'://'.$hostname.'/cgi-bin/listdomconfig.pl'; + } + my $domconf = &get_domain_config($perlvar{'lonDefDomain'},$primaryLibServer,$isprimary, + $url); + if (ref($domconf) eq 'HASH') { + if (ref($domconf->{'ssl'}) eq 'HASH') { + foreach my $connect ('connto','connfrom') { + if (ref($domconf->{'ssl'}->{$connect}) eq 'HASH') { + my ($sslreq,$sslnoreq,$currsetting); + my %contypes; + foreach my $type ('dom','intdom','other') { + $connectssl{$connect.'_'.$type} = $domconf->{'ssl'}->{$connect}->{$type}; + } + } + } + } + if (keys(%connectssl)) { + my %currconf; + if (open(my $fh,'<',"$perlvar{'lonTabDir'}/connectionrules.tab")) { + while (my $line = <$fh>) { + chomp($line); + my ($name,$value) = split(/=/,$line); + if ($value =~ /^(?:no|yes|req)$/) { + if ($name =~ /^conn(to|from)_(dom|intdom|other)$/) { + $currconf{$name} = $value; + } + } + } + close($fh); + } + if (open(my $fh,'>',"$perlvar{'lonTabDir'}/connectionrules.tab")) { + my $count = 0; + foreach my $key (sort(keys(%connectssl))) { + print $fh "$key=$connectssl{$key}\n"; + if (exists($currconf{$key})) { + unless ($currconf{$key} eq $connectssl{$key}) { + $changes{$key} = 1; + } + } else { + $changes{$key} = 1; + } + $count ++; + } + close($fh); + print "Completed writing SSL options for lonc/lond for $count items.\n"; + } + } else { + print "Writing of SSL options skipped - no connection rules in domain configuration.\n"; + } + } else { + print "Retrieval of SSL options for lonc/lond skipped - no configuration data available for domain.\n"; + } + return %changes; +} + +sub get_domain_config { + my ($dom,$primlibserv,$isprimary,$url) = @_; + my %confhash; + if ($isprimary) { + my $lonusersdir = $perlvar{'lonUsersDir'}; + my $fname = $lonusersdir.'/'.$dom.'/configuration.db'; + if (-e $fname) { + my $dbref=&LONCAPA::locking_hash_tie($fname,&GDBM_READER()); + if (ref($dbref) eq 'HASH') { + foreach my $key (sort(keys(%{$dbref}))) { + my $value = $dbref->{$key}; + if ($value =~ s/^__FROZEN__//) { + $value = thaw(&LONCAPA::unescape($value)); + } else { + $value = &LONCAPA::unescape($value); + } + $confhash{$key} = $value; + } + &LONCAPA::locking_hash_untie($dbref); + } + } + } else { + if (open(PIPE,"wget --no-check-certificate '$url?primary=$primlibserv&format=raw' |")) { + my $config = ''; + while () { + $config .= $_; + } + close(PIPE); + if ($config) { + my @pairs=split(/\&/,$config); + foreach my $item (@pairs) { + my ($key,$value)=split(/=/,$item,2); + my $what = &LONCAPA::unescape($key); + if ($value =~ s/^__FROZEN__//) { + $value = thaw(&LONCAPA::unescape($value)); + } else { + $value = &LONCAPA::unescape($value); + } + $confhash{$what}=$value; + } + } + } + } + return \%confhash; +} + +sub write_hosttypes { + my %intdom = &Apache::lonnet::all_host_intdom(); + my %hostdom = &Apache::lonnet::all_host_domain(); + my $dom = $hostdom{$perlvar{'lonHostID'}}; + my $internetdom = $intdom{$perlvar{'lonHostID'}}; + my %changes; + if (($dom ne '') && ($internetdom ne '')) { + if (keys(%hostdom)) { + my %currhosttypes; + if (open(my $fh,'<',"$perlvar{'lonTabDir'}/hosttypes.tab")) { + while (my $line = <$fh>) { + chomp($line); + my ($name,$value) = split(/:/,$line); + if (($name ne '') && ($value =~ /^(dom|intdom|other)$/)) { + $currhosttypes{$name} = $value; + } + } + close($fh); + } + if (open(my $fh,'>',"$perlvar{'lonTabDir'}/hosttypes.tab")) { + my $count = 0; + foreach my $lonid (sort(keys(%hostdom))) { + my $type = 'other'; + if ($hostdom{$lonid} eq $dom) { + $type = 'dom'; + } elsif ($intdom{$lonid} eq $internetdom) { + $type = 'intdom'; + } + print $fh "$lonid:$type\n"; + if (exists($currhosttypes{$lonid})) { + if ($type ne $currhosttypes{$lonid}) { + $changes{$lonid} = 1; + } + } else { + $changes{$lonid} = 1; + } + $count ++; + } + close($fh); + print "Completed writing host type data for $count hosts.\n"; + } + } else { + print "Writing of host types skipped - no hosts found.\n"; + } + } else { + print "Writing of host types skipped - could not determine this host's LON-CAPA domain or 'internet' domain.\n"; + } + return %changes; +} + +sub update_revocation_list { + my ($result,$changed) = &Apache::lonnet::fetch_crl_pemfile(); + if ($result eq 'ok') { + print "Certificate Revocation List (from CA) updated.\n"; + } else { + print "Certificate Revocation List from (CA) not updated.\n"; + } + return $changed; +} + +sub reset_nosslverify_pids { + my ($fh,%sslrem) = @_; + &checkon_daemon($fh,'lond',40000,'USR2'); + my $loncpidfile="$perlvar{'lonDaemons'}/logs/lonc.pid"; + my $loncppid; + if ((-e $loncpidfile) && (open(my $pfh,'<',$loncpidfile))) { + $loncppid=<$pfh>; + chomp($loncppid); + close($pfh); + if ($loncppid =~ /^\d+$/) { + my %pids_by_host; + my $docdir = $perlvar{'lonDocRoot'}; + if (-d "$docdir/lon-status/loncchld") { + if (opendir(my $dh,"$docdir/lon-status/loncchld")) { + while (my $file = readdir($dh)) { + next if ($file =~ /^\./); + if (open(my $fh,'<',"$docdir/lon-status/loncchld/$file")) { + my $record = <$fh>; + chomp($record); + close($fh); + my ($remotehost,$authmode) = split(/:/,$record); + $pids_by_host{$remotehost}{$authmode}{$file} = 1; + } + } + closedir($dh); + if (keys(%pids_by_host)) { + foreach my $host (keys(%pids_by_host)) { + if ($sslrem{$host}) { + if (ref($pids_by_host{$host}) eq 'HASH') { + if (ref($pids_by_host{$host}{'insecure'}) eq 'HASH') { + if (keys(%{$pids_by_host{$host}{'insecure'}})) { + foreach my $pid (keys(%{$pids_by_host{$host}{'insecure'}})) { + if (open(PIPE,"ps -o ppid= -p $pid |")) { + my $ppid = ; + chomp($ppid); + close(PIPE); + $ppid =~ s/(^\s+|\s+$)//g; + if (($ppid == $loncppid) && (kill 0 => $pid)) { + kill QUIT => $pid; + } + } + } + } + } + } + } + } + } + } + } + } + } + return; +} + sub send_mail { - print "sending mail\n"; - my $defdom = $perlvar->{'lonDefDomain'}; - my $origmail = $perlvar->{'lonAdmEMail'}; + my $defdom = $perlvar{'lonDefDomain'}; + my $origmail = $perlvar{'lonAdmEMail'}; my $emailto = &Apache::loncommon::build_recipient_list(undef, 'lonstatusmail',$defdom,$origmail); if ($totalcount>2500) { $emailto.=",$perlvar{'lonSysEMail'}"; } - my $subj="LON: $perlvar{'lonHostID'} E:$errors W:$warnings N:$notices"; - - my $result=system("metasend -b -S 4000000 -t $emailto -s '$subj' -f $statusdir/index.html -m text/html >& /dev/null"); - if ($result != 0) { - $result=system("mail -s '$subj' $emailto < $statusdir/index.html"); + my $from; + my $hostname=`/bin/hostname`; + chop($hostname); + $hostname=~s/[^\w\.]//g; + if ($hostname) { + $from = 'www@'.$hostname; + } + my $subj="LON: $perlvar{'lonHostID'} E:$errors W:$warnings N:$notices"; + my $loncronmail = "To: $emailto\n". + "From: $from\n". + "Subject: ".$subj."\n". + "Content-type: text/html\; charset=UTF-8\n". + "MIME-Version: 1.0\n\n"; + if (open(my $fh,"<$statusdir/index.html")) { + while (<$fh>) { + $loncronmail .= $_; + } + close($fh); + } else { + $loncronmail .= "Failed to read from http://$hostname/lon-status/index.html\n"; + } + $loncronmail .= "\n\n"; + if (open(my $mailh, "|/usr/lib/sendmail -oi -t -odb")) { + print $mailh $loncronmail; + close($mailh); + print "Sending mail.\n"; + } else { + print "Sending mail failed.\n"; } } sub usage { print(< /dev/null"); + system("echo 'Unconfigured machine $hostname.' |". + " mail -s '$subj' $emailto > /dev/null"); exit 1; } # ----------------------------- Make sure this process is running from user=www my $wwwid=getpwnam('www'); if ($wwwid!=$<) { - print("User ID mismatch. This program must be run as user 'www'\n"); + print("User ID mismatch. This program must be run as user 'www'.\n"); my $emailto="$perlvar{'lonAdmEMail'},$perlvar{'lonSysEMail'}"; my $subj="LON: $perlvar{'lonHostID'} User ID mismatch"; - system("echo 'User ID mismatch. loncron must be run as user www.' |\ - mailto $emailto -s '$subj' > /dev/null"); + system("echo 'User ID mismatch. loncron must be run as user www.' |". + " mail -s '$subj' $emailto > /dev/null"); exit 1; } # -------------------------------------------- Force reload of host information - &Apache::lonnet::load_hosts_tab(1); - &Apache::lonnet::load_domain_tab(1); - &Apache::lonnet::get_iphost(1); + my $nomemcache; + if ($justcheckdaemons) { + $nomemcache=1; + my $memcachepidfile="$perlvar{'lonDaemons'}/logs/memcached.pid"; + my $memcachepid; + if (-e $memcachepidfile) { + my $memfh=IO::File->new($memcachepidfile); + $memcachepid=<$memfh>; + chomp($memcachepid); + if ($memcachepid =~ /^\d+$/ && kill 0 => $memcachepid) { + undef($nomemcache); + } + } + } + &Apache::lonnet::load_hosts_tab(1,$nomemcache); + &Apache::lonnet::load_domain_tab(1,$nomemcache); + &Apache::lonnet::get_iphost(1,$nomemcache); + +# ----------------------------------------- Force firewall update for lond port + + if ((!$justcheckdaemons) && (!$justreload)) { + my $now = time; + my $tmpfile = $perlvar{'lonDaemons'}.'/tmp/lciptables_iphost_'. + $now.$$.int(rand(10000)); + if (open(my $fh,">$tmpfile")) { + my %iphosts = &Apache::lonnet::get_iphost(); + foreach my $key (keys(%iphosts)) { + print $fh "$key\n"; + } + close($fh); + if (&LONCAPA::try_to_lock('/tmp/lock_lciptables')) { + my $execpath = $perlvar{'lonDaemons'}.'/lciptables'; + system("$execpath $tmpfile"); + unlink('/tmp/lock_lciptables'); # Remove the lock file. + } + unlink($tmpfile); + } + } # ---------------------------------------------------------------- Start report @@ -687,6 +1246,7 @@ sub main () { &log_machine_info($fh); &clean_tmp($fh); &clean_lonIDs($fh); + &clean_webDAV_sessionIDs($fh); &check_httpd_logs($fh); &rotate_lonnet_logs($fh); &rotate_other_logs($fh); @@ -699,8 +1259,13 @@ sub main () { } &checkon_daemon($fh,'lonc',40000,'USR1'); &checkon_daemon($fh,'lonmaxima',40000); + &checkon_daemon($fh,'lonr',40000); } if ($justreload) { + &clean_nosslverify($fh); + &write_connection_config(); + &write_hosttypes(); + &update_revocation_list(); &checkon_daemon($fh,'lond',40000,'USR2'); &checkon_daemon($fh,'lonc',40000,'USR2'); } @@ -709,9 +1274,20 @@ sub main () { } if (!$justcheckdaemons && !$justcheckconnections && !$justreload) { &check_delayed_msg($fh); - &finish_logging($fh); &log_simplestatus(); - + &write_loncaparevs(); + &write_serverhomeIDs(); + &write_checksums(); + my %sslrem = &clean_nosslverify($fh); + my %conchgs = &write_connection_config(); + my %hosttypechgs = &write_hosttypes(); + my $hadcrlchg = &update_revocation_list(); + if ((keys(%conchgs) > 0) || (keys(%hosttypechgs) > 0) || + $hadcrlchg || (keys(%sslrem) > 0)) { + &checkon_daemon($fh,'lond',40000,'USR2'); + &reset_nosslverify_pids($fh,%sslrem); + } + &finish_logging($fh); if ($totalcount>200 && !$noemail) { &send_mail(); } } } @@ -719,10 +1295,3 @@ sub main () { &main(); 1; - - - - - - - 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.