5 from collections
import OrderedDict
10 PERMISSION_RW_R = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP
12 PERMISSION_RW_R_R = stat.S_IRUSR | stat.S_IWUSR | stat.S_IRGRP | stat.S_IROTH
15 if os.path.isfile(path):
17 print "Warning, not a file: ", path
22 os.chmod(path, permission)
32 while size > 0
and bytes > 0:
33 if (bytes - BUFSIZ > 0):
35 f.seek(block*BUFSIZ, 2)
37 data.append(f.read(BUFSIZ))
42 data.append(f.read(bytes))
43 linesFound = data[-1].
count(
'\n')
47 return '\n'.join(
''.join(data).splitlines()[-window:])
62 return "Process " +
str(self.
num) +
", last message: \n" + self.
lastMsg()
74 return self.
num == other.num
and self.proj.logPath == other.proj.logPath
96 wildcard = self.proj.logPath.replace(
".log",
"*.%s.err" %(
str(self.
num)))
97 files = glob.glob(wildcard)
99 raise Exception(
"Too many (%s) files found matching path %s" 100 % (len(files), wildcard))
107 wildcard = self.proj.logPath.replace(
".log",
"*.%s.out" %(
str(self.
num)))
108 files = glob.glob(wildcard)
110 raise Exception(
"Too many (%s) files found matching path %s" 111 % (len(files), wildcard))
121 return tail(path, window)
128 return tail(path, window)
135 print os.system(
"less " + path)
143 print os.system(
"less " + path)
149 if not "return value" in self.
lastMsg():
151 start = self.
lastMsg().find(
"return value")
153 end = self.
lastMsg().find(
")", start)
154 valStr = self.
lastMsg()[start:end]
155 values = valStr.split()
157 return int(values[2])
159 raise Exception(
"Can't find return code, improperly fomatted message: %s" 163 states = [
"normal",
"abnormal",
"incomplete"]
190 if self.logPath.endswith(
".cmd"):
191 print "Condor .cmd file supplied, swapping extension for .log" 192 self.
logPath = logPath.replace(
".cmd",
".log")
212 if line.strip() ==
"...":
213 self.msgs.append(msg)
224 for msg
in self.
msgs:
230 if smsg[1][0] ==
"(":
232 num =
int(numStr.split(
".")[1])
233 if num
in self.procs.keys():
234 self.
procs[num].addMsg(msg)
237 self.
procs[num].addMsg(msg)
242 print "Found", self.
nProcs(),
"processes." 246 for key
in sorted(self.procs.keys()):
257 if sequential
and firstKey == 0:
258 print "Process numbers are sequential starting with %s, things seem ok."\
261 print "Process numbers are sequential, but do not start with 0. " + \
262 "Be careful with your indexing." 263 print "First process number is %s." % (
str(firstKey))
265 print "Process numbers are not sequential, be careful with your indexing." 268 for proc
in self.procs.values():
269 if proc.retCode() == 0:
271 elif proc.retCode() > 0:
279 print len(self.
stateMap[
"normal"]), \
280 "of those processes ended normally with status 0" 281 print len(self.
stateMap[
"abnormal"]), \
282 "of those processes ended normally but with non-zero status" 283 print len(self.
stateMap[
"incomplete"]), \
284 "of those processes are either still in progress ended abnormally" 288 for proc
in self.procs.values():
289 splitMsg = proc.lastMsg().
split()
291 mode =
int(splitMsg[0])
293 raise Exception(
"Could not find mode (three digits) at the beginning" +\
294 "of this message: " +
str(proc))
296 if not mode
in self.decomp.keys():
301 for mode
in self.decomp.values():
303 if not sum == self.
nProcs():
304 raise Exception(
"Sum of decomposed processes not equal to total number "+\
308 print "Jobs have", len(self.
decomp),
"different modes. "+\
309 "Here is an example of each." 310 for mode
in self.decomp.keys():
311 print "* Mode", mode,
"-- there are", len(self.
decomp[mode]), \
312 "of these, one example is:" 313 for line
in str(self.
decomp[mode][0]).splitlines():
319 return len(self.
procs)
327 return len(self.
procs)
331 for key
in self.procs.keys():
332 yield self.
procs[key]
337 for proc
in self.procs.values():
344 logDirContents = os.listdir(logDir)
345 for fileName
in logDirContents:
346 if fileName.endswith(
".log"):
347 return os.path.join(logDir,fileName)
353 print "JobSub Client Job ID supplied, finding logs." 354 if "CONDOR_TMP" in os.environ
and os.path.isdir(os.environ[
"CONDOR_TMP"]):
355 print "Found $CONDOR_TMP, logs will be stored there. " 356 fetchLocation = os.environ[
"CONDOR_TMP"]
358 print "Failed to find $CONDOR_TMP, fetching logs to current directory." 361 logDir = os.path.join(fetchLocation, jobId)
363 if not os.path.isdir(logDir):
365 print "Directory:", logDir
368 print "Log file previously fetched, location:", extantLogFile
372 print "Fetching log files..." 373 os.system(
"jobsub_fetchlog --jobid " + jobId +
" --unzipdir " + logDir)
377 print "Log file location:", fetchedLogFile
378 return fetchedLogFile
380 raise Exception(
"Failed to filnd log file after fetching, " + \
381 "something went wrong.")
390 os.system(
"less " + self.
path)
400 parser = argparse.ArgumentParser(description=
""" 401 Loop over the ".log" file and find the final state of each 402 process, then find the .err and .out""")
403 parser.add_argument(
'logFile', help=
""" 404 The input file to run over, or a jobsub_client jobid. 405 In the jobid case, the files are fetched to CONDOR_TMP if it is defined, 406 or falls back to the current working directory if not defined. If the log 407 has already been fetcheded, it just finds it there.""", type=str)
409 args = parser.parse_args()
410 logPath = args.logFile
412 if not os.path.isfile(logPath)
and "@" in logPath
and ".fnal.gov" in logPath:
421 if __name__ ==
"__main__":
423 code.interact(local=locals(), banner=
"")
void split(double tt, double *fr)
def errPath(self)
Get the path to the std err file.
def separateMessages(self)
separateMessages() turns all of the separate messages in the file into entries in a list...
def errTail(self, window=20)
Tail the std err file.
def outPath(self)
Get the path to the std out file.
def __init__(self, num, proj)
def processRecon(self)
processRecon() loops over all the messages to make Process objects, fills a dict. ...
def findLogInDirectory(logDir)
def __contains__(self, test)
def outLess(self)
Open the std err file with less.
def __getitem__(self, n)
Implementation of [] operator for indexing.
def retreiveLogFromJobSubClient(jobId)
procfile open("FD_BRL_v0.txt")
def errLess(self)
Open the std out file with less.
cet::coded_exception< errors::ErrorCodes, ExceptionDetail::translate > Exception
def retCode(self)
Find the return code from the last message, -1 if last message is not normal termination.
def tail(path, window=20)
def inspectProcs(self)
Inspect the processes, make sure the numbers jive and decompose them into "normal" and "abnormal"...
def makeReadable(self, permission=PERMISSION_RW_R_R)
Make .log and all .err and .out group readable and user read/writable.
def setPermission(path, permission=PERMISSION_RW_R_R)
def nProcs(self)
Number of process objects in dict.
def __init__(self, logPath)
def outTail(self, window=20)
Tail the std out file.