# chkjobs.pl checks jobs in AT scheduler queue on remote NT computers # and reports missing jobs. # Written 3-Mar-1998 by fhb. # Usage: chkjobs.pl jobfile computerfile # where jobfile contains list of required jobs (command string only), # and computerfile contains list of remote computer names. # # Mod 6-mar-1998 by fhb: added /output and /notify options; ver 1.1. # Note that BLAT must be in the path in order for /notify to work. # Mod 11-mar-1998 by fhb: if no missing jobs print 'all is well'; # print '.' for each computer checked for dynamic feedback. # Mod 20-dec-2000 by fgb: added /submit and /every args. require "ctime.pl"; use Net::Ping; $bDebug = 0; MAIN: $sAppName = "ChkJobs"; $sDate = &ctime(time); $sEvery = "su"; $bNotify = 0; $sRptFile = "chkjobs-msg.rpt"; # set default for notify $bSubmit = 0; $sSubTime = "12:00"; $sTempFile = "t.t"; $sTmp = ""; $sToday = substr($sDate,4); $nTotalBad = 0; $nTotalComputers = 0; $nTotalGood = 0; $bUseRptFile = 0; $sVersion = "1.2"; print "$sAppName $sVersion "; unless ($#ARGV + 1) { die "Missing data file on command line.\n"; # somebody give me an arg! } $sJobFile = $ARGV[0]; $sComputerFile = $ARGV[1]; ParseCmdArgs(); # must FOLLOW any arg use! open(FJOBS,$sJobFile) || die "Can't open file $sJobFile: $!\n"; @lJobs = ; # read jobs into list close(FJOBS); $nJobCount = @lJobs; if (0 == $nJobCount) { ### this doesn't work ### die "Empty job list\n"; } else { foreach $sReqJob (@lJobs) { # eat newlines chop $sReqJob; } print "Checking for existence of $nJobCount job"; if ($nJobCount > 1) { print "s"; } print " at $sToday..."; } # Check each computer: open(FPCDATA,$sComputerFile) || die "Can't open file $sComputerFile: $!\n"; if ($bUseRptFile) { $sTmp = sprintf(">%s",$sRptFile); if ($bDebug) { print "sTmp = $sTmp\n"; } open(RPTFILE,$sTmp) || die "Can't open file $sRptFile: $!\n"; print RPTFILE "$sAppName $sVersion report generated at $sToday\n\n"; } while () { if (!/^\!/) { # skip comments chop $_; s/\s(.*)//; # remove whitespace s/^\\\\//; # remove leading '\\' $sComputer = $_; if (&IsVis()) { ChkForJob(); } ++$nTotalComputers; print "."; } } close(FPCDATA); print "\n$sAppName: checked $nTotalComputers computers.\n"; if ($nTotalBad > 0) { $sTmp = "$nTotalBad jobs missing!\n"; print $sTmp; if ($bUseRptFile) { print RPTFILE $sTmp; close(RPTFILE); } if ($bNotify) { Notify(); } } else { print "All is well.\n"; if ($bUseRptFile) { # no missing jobs, so unlink $sRptFile; # delete empty rpt file } } ########### subroutines eh? ############ sub ChkForJob { # Capture output of AT command to list running jobs in temp file: $sCmd = sprintf("at \\\\%s >%s",$sComputer,$sTempFile); if ($bDebug) { print "dbg> $sCmd\n"; } system($sCmd); # Parse file of running jobs into array lRunningJobs: @lRunningJobs = (); open(FTEMP,$sTempFile) || print "Can't open file $sTempFile: $!\n"; while () { chop $_; if (/^\ (.*)/) { # find lines beginning w ' ' $sThisJob = substr($_,50); push(@lRunningJobs,$sThisJob); } } close(FTEMP); # Check each required job against each item in list of running jobs: foreach $sReqJob (@lJobs) { $bFound = 0; foreach $_ (@lRunningJobs) { # if (/$sReqJob/) { ### why doesn't this work? ### if ($sReqJob eq $_) { $nTotalGood++; $bFound = 1; if ($bDebug) { print "Found $sReqJob in @lRunningJobs\n"; } last; } } if ($bFound == 0) { $nTotalBad++; $sTmp = "$sReqJob not running on $sComputer\n"; print $sTmp; if ($bUseRptFile) { print RPTFILE $sTmp; } if ($bDebug) { print "dbg: $#lJobs in jobs list\n"; } if ($bSubmit && ($nJobCount == 1)) { print "Submitting $lJobs[0] on $sComputer\n"; $sCmd = sprintf("AT \\\\%s %s /every:%s %s",$sComputer,$sSubTime,$sEvery,$lJobs[0]); if ($bDebug) { print "dbg: $sCmd\n"; } else { system($sCmd); } } } } if ($bDebug == 0) { unlink $sTempFile; } } sub Help { printf("%s version %s\n",$sAppName,$sVersion); printf("\nUsage: %s joblist computerlist [options]\n",$sAppName); print "\nOptions: /output=filename <-- save output to a file\n"; print " /notify <-- email output (if jobs missing)\n"; print " /submit=time <-- submit job if not running\n"; print " /every: <-- the AT command's arg\n"; } sub IsVis { $p = Net::Ping->new("icmp"); return ($p->ping($sComputer,1)); } sub Notify { @Recipients = ('frank.brown','willard.shockey','ken.fairbanks'); $sMailDomain = "ci.seattle.wa.us"; print "Sending email...\n"; foreach $sName (@Recipients) { $sToList .= sprintf("%s\@%s,",$sName,$sMailDomain); } chop($sToList); # chop last comma from recipient list $sCmd = sprintf("blat %s -t %s -s \"Missing AT jobs\"",$sRptFile,$sToList); if ($bDebug) { print "dbg: $sCmd\n"; } else { system($sCmd); } } sub ParseCmdArgs { while (@ARGV) { $_ = shift @ARGV; if ($bDebug) { print "dbg: parsing $_\n"; } if (/^[\/\-]/) { # is arg a switch? $arg = substr($_,1,3); # parse 1st 3 chars: # ternary operator doesn't work so don't use it! if ($arg eq "eve") { $i = index($_,":"); $i++; $sEvery = sprintf("%s",substr($_,$i)); } if ($arg eq "sub") { $bSubmit = 1; $i = index($_,"="); $i++; $sSubTime = sprintf("%s",substr($_,$i)); } if ($arg eq "not") { $bNotify = 1; $bUseRptFile = 1; # need file to email to recipients } if (($arg eq "hel") || (substr($arg,0,1) eq "?")) { &Help(); exit; } if ($arg eq "out") { $i = index($_,"="); $i++; $sRptFile = sprintf("%s",substr($_,$i)); if ($sRptFile eq $sTempFile) { $sRptFile .= "2"; # prevent dup filename } $bUseRptFile = 1; } } } if ($bDebug) { print "dbg: bNotify = $bNotify\n"; print "dbg: bSubmit = $bSubmit\n"; print "dbg: sSubTime = $sSubTime\n"; print "dbg: sEvery = $sEvery\n"; print "dbg: sRptFile = $sRptFile\n"; print "dbg: bUseRptFile = $bUseRptFile\n"; } }