--- loncom/loncron 2009/06/11 00:15:27 1.81
+++ loncom/loncron 2013/02/08 14:49:51 1.98
@@ -2,7 +2,7 @@
# Housekeeping program, started by cron, loncontrol and loncron.pl
#
-# $Id: loncron,v 1.81 2009/06/11 00:15:27 raeburn Exp $
+# $Id: loncron,v 1.98 2013/02/08 14:49:51 raeburn Exp $
#
# Copyright Michigan State University Board of Trustees
#
@@ -32,6 +32,8 @@ use strict;
use lib '/home/httpd/lib/perl/';
use LONCAPA::Configuration;
+use LONCAPA::Checksumming;
+use LONCAPA;
use Apache::lonnet;
use Apache::loncommon;
@@ -269,12 +271,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);
@@ -347,33 +344,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}):- ".
+ join('
- ',@{$errors{$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
@@ -420,21 +511,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);
}
@@ -470,12 +553,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,7 +623,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");
@@ -549,11 +639,28 @@ sub check_delayed_msg {
}
&log($fh,"
\n");
close (DFH);
+ my %hostname = &Apache::lonnet::all_hostnames();
+ my $numhosts = scalar(keys(%hostname));
# 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'.
");
+ }
}
}
@@ -586,6 +693,84 @@ 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 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 send_mail {
print "sending mail\n";
my $defdom = $perlvar{'lonDefDomain'};
@@ -686,9 +871,12 @@ sub main () {
print $fh "$key\n";
}
close($fh);
- my $execpath = $perlvar{'lonDaemons'}.'/lciptables';
- system("$execpath $tmpfile");
- unlink($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);
}
}
@@ -731,7 +919,9 @@ sub main () {
&check_delayed_msg($fh);
&finish_logging($fh);
&log_simplestatus();
-
+ &write_loncaparevs();
+ &write_serverhomeIDs();
+ &write_checksums();
if ($totalcount>200 && !$noemail) { &send_mail(); }
}
}
@@ -739,10 +929,3 @@ sub main () {
&main();
1;
-
-
-
-
-
-
-