#!/usr/bin/perl require 5.006; BEGIN { use File::Basename; my $binDir = dirname($0); unshift(@INC, "$binDir" ); } use setup; setup::setupEnv(); while (@ARGV) { $arg = shift @ARGV; if ( $arg =~ /^-verbose\z/ ) { $VERBOSE = 1; } elsif ( $arg =~ /-v/ ) { $GET_VERSION = 1; $WDOG = undef; last; } elsif ( $arg =~ /-email/ ) { $EMAIL = shift @ARGV; } elsif ( $arg =~ /-pause/ ) { $PAUSE = shift @ARGV; } elsif ( $arg =~ /-wdog/ ) { $WDOG = 1; } else { usage(); } } if ($WDOG) { defined(my $dpid = fork) or die "**F: Failed to fork - $!"; if ($dpid) { #print "Detach terminal\n"; exit 0; # detach the terminal, child continues below } else { setpgrp (0,0) if ($setup::sysname != /^win/i ); } } $BUILD_ROOTDIR = $setup::BUILD_ROOTDIR; $JAVA_BIN = $setup::JAVA_BIN; use reputils; reputils::checkJava($JAVA_BIN); $PREFS_ROOT = $setup::PREFS_ROOT; $LOG_DIR = $setup::LOG_DIR; mkdir($LOG_DIR) if !-e $LOG_DIR; $DB_DIR = "$BUILD_ROOTDIR/systemdb"; if (!-e $DB_DIR) { $created = mkdir($DB_DIR); if (!$created) { die "Failed to mkdir $DB_DIR\n"; } } $CORRUPTED_FLAG = "$DB_DIR/corrupted"; if (-e $CORRUPTED_FLAG) { my $MSG =<< "EOM"; FATAL ERROR: The recovery logs are corrupted. \tReport the problem with a talkback tarball to . \tThen, follow the CLEAN RESTART procedure described in the Admin Guide. EOM die "$MSG"; } $CP = $setup::CP; $PERL_PATH = reputils::path2perl(); $SYS_PROPS = "$setup::EGD -Dlog.dir=$BUILD_ROOTDIR -Dprefs.root=$PREFS_ROOT -Derr.catalog.dir=$BUILD_ROOTDIR/config -Djava.io.tmpdir=$DB_DIR -Duse.soap=off -Dperl.path=$PERL_PATH"; # Ony version check needs ? version() if ($GET_VERSION); # will exit # Check another process running #$JPDA = $ENV{JPDA}; $CHECK = "org.nirala.admin.DConeUpChecker"; $checkCmd = "$JAVA_BIN/java $reputils::CLIENT_JVM_ARGS $JPDA -cp \"$CP\" $SYS_PROPS $CHECK"; system($checkCmd); if ($? != 0) { exit(-1); } # Execute Main Program $MAIN = "org.nirala.communication.transport.cvsproxy.ProxyServer"; $SYS_PROPS .= " -Demail=$EMAIL" if $EMAIL; $READONLY_SYS_PROPS = "$SYS_PROPS -Dproxy.mode=readonly"; $JVMARGS = "$reputils::SERVER_JVM_ARGS"; $runCmd = "$JAVA_BIN/java $JVMARGS $JPDA -cp \"$CP\" $SYS_PROPS $MAIN"; $runReadOnlyCmd = "$JAVA_BIN/java $JVMARGS $JPDA -cp \"$CP\" $READONLY_SYS_PROPS $MAIN"; #=== Run Main Now ==== mainrun(); #=== END ============ #---- SUBS ------------- sub mainrun { $PGID = $$; if ($WDOG) { $MAX_DEATHS = 10; $MAX_RW = $MAX_DEATHS - 1; watchdog(); } else { executeMain(); } } sub watchdog { my $done = 0; my $ndeaths = 0; $readonly = 0; my $MIN_UPTIME = 30; # 30s while($ndeaths < $MAX_DEATHS) { # If 10 successive deaths every 30s bail out if ($ndeaths == ($MAX_RW - 1)) { $readonly = 1; } defined(my $pid = fork) or die "**F: Failed to fork - $!"; if ($pid) { ## parent: if ($ndeaths == 0) { emailRestart($EMAIL) if $EMAIL; } if ($readonly == 1) { emailReadonly($EMAIL) if $EMAIL; } my $start = time; waitpid $pid, 0; # block my $end = time; my $rc = $? >> 8; if ($rc == 19) { emailNormalShutdown($EMAIL) if $EMAIL; ; exit($rc); # Normal shutdown } if ($rc == 37) { # corrupted recovery log emailCorrupt($EMAIL) if $EMAIL; system("touch $CORRUPTED_FLAG"); exit($rc); } my $life = $end - $start; if ($life < $MIN_UPTIME) { $ndeaths++; } else { $ndeaths = 0; # reset count $readonly = 0; } sleep $PAUSE; # before restarting service } else { ## child: executeMain(); } } # exceeded the death rate my $minUptimeSec = int($MIN_UPTIME/1000); emailShutdown($EMAIL) if $EMAIL; die "**F: Watchdog is terminating....$MAX_DEATHS process exits occured within ${minUptimeSec}s of each other\n"; } sub executeMain { if ($readonly == 1) { $cmd = $runReadOnlyCmd; } else { $cmd = "$runCmd"; } if ($VERBOSE) { print "Executing ....\n\t$cmd\n"; } else { $log = "$LOG_DIR/console.txt"; &setup::redirectSTDIO($log); } # Save PGID for latter shutdown $PGID = getpgrp() if ($setup::sysname != /^win/i ); system("echo $PGID > $LOG_DIR/my.pid"); system("echo $$ > $LOG_DIR/java.pid"); # Become the image so that SIGQUIT etc can work on the script itself # save output from JVM like thread dump in $LOG_DIR/console.txt file exec "$cmd"; } sub emailNormalShutdown { my $TO = $_[0]; my $host = (POSIX::uname())[1]; my $SUBJECT = "[$host:SYSTEM ALERT] WANdisco CVS Replicator Normal Shutdown"; my $now = `date`; my $MSG = "$now\nNormal shutdown was completed\n"; my $FROM = "wdog\@cvsreplicator.org"; setup::sendEmail($SUBJECT, $MSG, $TO, $FROM); } sub emailShutdown { my $TO = $_[0]; my $host = (POSIX::uname())[1]; my $SUBJECT = "[$host:SYSTEM ALERT] WANdisco CVS Replicator Shutdown"; my $now = `date`; my $MSG = "$now\nAfter $MAX_DEATHS attempts, failed to restart service, please look at the ProxyServer*log files"; my $FROM = "wdog\@cvsreplicator.org"; setup::sendEmail($SUBJECT, $MSG, $TO, $FROM); } sub emailCorrupt { my $TO = $_[0]; my $host = (POSIX::uname())[1]; my $SUBJECT = "[$host:SYSTEM ALERT] WANdisco CVS Replicator Shutdown"; my $now = `date`; my $MSG = "$now\nDetected possible corruption of recovery logs. Please look at the ProxyServer*log files"; my $FROM = "wdog\@cvsreplicator.org"; setup::sendEmail($SUBJECT, $MSG, $TO, $FROM); } sub emailRestart { my $TO = $_[0]; my $host = (POSIX::uname())[1]; my $SUBJECT = "[$host:SYSTEM ALERT] WANdisco CVS Replicator Restarting"; my $now = `date`; my $MSG = "$now\tThe cvsreplicator watchdog is restarting service"; my $FROM = "wdog\@cvsreplicator.org"; setup::sendEmail($SUBJECT, $MSG, $TO, $FROM); } sub emailReadonly { my $TO = $_[0]; my $host = (POSIX::uname())[1]; my $SUBJECT = "[$host:SYSTEM ALERT] WANdisco CVS Replicator Restarting In Readonly Mode"; my $now = `date`; my $MSG = "$now\tThe cvsreplicator watchdog is restarting service in readonly mode"; my $FROM = "wdog\@cvsreplicator.org"; setup::sendEmail($SUBJECT, $MSG, $TO, $FROM); } sub version { $vercheck = "org.nirala.admin.cvsproxy.VersionChecker"; $checkCmd = "$JAVA_BIN/java $reputils::CLIENT_JVM_ARGS $JPDA -cp \"$CP\" $SYS_PROPS $vercheck"; system($checkCmd); if ($? != 0) { exit(-1); } exit(0); } sub usage { $USG =<< "EOM"; Usage: cvsreplicator [-v] [-verbose] [ -wdog [-pause time] [-email email-address] ] \t-v\tPrint the cvsreplicator version \t-verbose \t\tVerbose, console messages go to STDOUT/STDERR \t \tinstead of logs/console.txt \t-wdog \t\tWatchdog mode, cvsreplicator will start a watchdog \t \twhich can automatically restart cvsreplicator process \t \tif it terminates. \t-pause \t\tTime in seconds that the watchdog will pause for, before \t \trestarting service. Defaults to 0 seconds. \t-email \t\tSpecify an email address to send an alert to, whenever the \t \tWatchdog restarts/shuts down the cvsreplicator service. \t \tFor email alert to work, sendmail or sendmail wrapper must be \t \tinstalled in /usr/sbin/sendmail. You may want to test it by \t \trunning "sendmail -t" first. Report any issues to . EOM die "$USG"; }