--- loncom/loncron 2007/04/13 18:26:22 1.73 +++ loncom/loncron 2011/11/03 22:32:04 1.93 @@ -2,7 +2,7 @@ # Housekeeping program, started by cron, loncontrol and loncron.pl # -# $Id: loncron,v 1.73 2007/04/13 18:26:22 albertel Exp $ +# $Id: loncron,v 1.93 2011/11/03 22:32:04 raeburn Exp $ # # Copyright Michigan State University Board of Trustees # @@ -32,7 +32,9 @@ use strict; use lib '/home/httpd/lib/perl/'; use LONCAPA::Configuration; +use LONCAPA; use Apache::lonnet; +use Apache::loncommon; use IO::File; use IO::Socket; @@ -81,7 +83,9 @@ sub start_daemon { } my $error_fname="$perlvar{'lonDaemons'}/logs/${daemon}_errors"; &rotate_logfile($error_fname,$fh,'error logs'); - + if ($daemon eq 'lonc') { + &clean_sockets($fh); + } system("$perlvar{'lonDaemons'}/$progname 2>$perlvar{'lonDaemons'}/logs/${daemon}_errors"); sleep 1; if (-e $pidfile) { @@ -302,7 +306,6 @@ sub start_logging {
  • lonsql
  • lond
  • lonc
  • -
  • lonhttpd
  • lonnet
  • Connections
  • Delayed Messages
  • @@ -345,33 +348,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}):
    '); + } + } + } +} + +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); } - &log($fh,"Cleaned up ".$cleaned." files (".$old." old checkout tokens)."); + return ($cleaned,$old,$removed); } # ------------------------------------------------------------ clean out lonIDs @@ -399,25 +496,32 @@ sub clean_lonIDs { &log($fh,"

    $active open session(s)

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

    Cleaned up ".$cleaned." stale 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); } @@ -453,12 +557,17 @@ 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 @@ -535,8 +644,18 @@ sub check_delayed_msg { # 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
    "); + my $answer; + eval { + local $SIG{ ALRM } = sub { die "TIMEOUT" }; + alarm(20); + $answer = &Apache::lonnet::reply("pong",$tryserver); + alarm(0); + }; + if ($@ && $@ =~ m/TIMEOUT/) { + print "time out while contacting: $tryserver for pong\n"; + } else { + &log($fh,"Pong to $tryserver: $answer
    "); + } } } @@ -569,9 +688,70 @@ sub log_simplestatus { $sfh->close(); } +sub write_loncaparevs { + print "Retrieving LON-CAPA version information\n"; + if (open(my $fh,">$perlvar{'lonTabDir'}/loncaparevs.tab")) { + my %hostname = &Apache::lonnet::all_hostnames(); + 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.\-]+$/) { + print $fh $id.':'.$loncaparev."\n"; + } + } + } + close($fh); + } + return; +} + +sub write_serverhomeIDs { + print "Retrieving LON-CAPA lonHostID information\n"; + if (open(my $fh,">$perlvar{'lonTabDir'}/serverhomeIDs.tab")) { + my %name_to_host = &Apache::lonnet::all_names(); + 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 '') { + print $fh $name.':'.$serverhomeID."\n"; + } else { + print $fh $name.':'.$name_to_host{$name}->[0]."\n"; + } + } + } + } + close($fh); + } + return; +} + sub send_mail { print "sending mail\n"; - my $emailto="$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'}"; } @@ -623,7 +803,7 @@ sub main () { undef $perlvarref; delete $perlvar{'lonReceipt'}; # remove since sensitive and not needed delete $perlvar{'lonSqlAccess'}; # remove since sensitive and not needed - + chdir($perlvar{'lonDaemons'}); # --------------------------------------- Make sure that LON-CAPA is configured # I only test for one thing here (lonHostID). This is just a safeguard. if ('{[[[[lonHostID]]]]}' eq $perlvar{'lonHostID'}) { @@ -654,6 +834,27 @@ sub main () { &Apache::lonnet::load_domain_tab(1); &Apache::lonnet::get_iphost(1); +# ----------------------------------------- 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 $errors=0; @@ -673,14 +874,14 @@ sub main () { &rotate_other_logs($fh); } if (!$justcheckconnections && !$justreload) { + &checkon_daemon($fh,'lonmemcached',40000); &checkon_daemon($fh,'lonsql',200000); if ( &checkon_daemon($fh,'lond',40000,'USR1') eq 'running') { &checkon_daemon($fh,'lond',40000,'USR2'); } &checkon_daemon($fh,'lonc',40000,'USR1'); - &checkon_daemon($fh,'lonhttpd',40000); - &checkon_daemon($fh,'lonmemcached',40000); &checkon_daemon($fh,'lonmaxima',40000); + &checkon_daemon($fh,'lonr',40000); } if ($justreload) { &checkon_daemon($fh,'lond',40000,'USR2'); @@ -693,6 +894,8 @@ sub main () { &check_delayed_msg($fh); &finish_logging($fh); &log_simplestatus(); + &write_loncaparevs(); + &write_serverhomeIDs(); if ($totalcount>200 && !$noemail) { &send_mail(); } }