def runAndMonitor(self): """""" proc = procc.Process(self.__dict__) self.processes.append(proc) proc.start() log("Program '" + self.progname + "' process starting", "./tmlog.txt", False)
def do_exit(self, args): '''Exits the Taskmaster shell when user inputs "exit"''' self.monitor = False if (len(self.programs) > 0): self.stopAllPrograms() log("TaskMaster exiting", "./tmlog.txt", False) exit(0)
def stopPrograms(self, args): """""" cnt = 1 num = 0 procs = 0 found = False if (len(args) == 1): print("Please specify which program\s to stop." + "\n(stop all -OR- stop [program1 name] " + "[program2 name])") elif (len(args) > 1): if (args[1] == "all"): num = self.activePrograms() if (num == 0): print("All programs already stopped") return for prog in self.programs: if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == True and proc.pop.returncode == None): proc.stop = True proc.stopping = True signum = tmfuncs.getSignalValue(prog.stopsig) proc.pop.send_signal(signum) procs += 1 else: while cnt < len(args): for prog in self.programs: if (prog.progname == args[cnt]): found = True if (prog.hasActiveProcesses() == False): print("Program '" + prog.progname + "' already stopped") break num += 1 if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == True and proc.pop.returncode == None): proc.stop = True proc.stopping = True signum = tmfuncs.getSignalValue( prog.stopsig) proc.pop.send_signal(signum) procs += 1 if (found == False): log("No program '" + args[cnt] + "' in config", "./tmlog.txt", True) found = False cnt += 1 if (num > 0): print("Stopping " + str(num) + " program\s. Please wait...") self.waitForPrograms() print(str(procs) + " process\es stopped.") num = 0
def startPrograms(self, args): """""" cnt = 1 num = 0 procs = 0 found = False if (len(args) == 1): print("Please specify which program\s to start." + "\n(start all -OR- start [program1 name] " + "[program2 name])") elif (len(args) > 1): if (args[1] == "all"): if (self.allProgramsActive() == True): print("All programs already active. Use 'restart' to" + " restart all programs") return num = (len(self.programs)) - (self.activePrograms()) for prog in self.programs: if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == False): procs += 1 proc.timetostart = 0 proc.run() else: # for programs not yet launched procs += prog.runAndMonitor() else: while cnt < len(args): for prog in self.programs: if (prog.progname == args[cnt]): found = True if (prog.hasInactiveProcesses() == False and len(prog.processes) > 0): print("Program '" + prog.progname + "' already started") break num += 1 if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == False): procs += 1 proc.timetostart = 0 proc.run() else: procs += prog.runAndMonitor() if (found == False): log("No program '" + args[cnt] + "' in config", "./tmlog.txt", True) found = False cnt += 1 if (num > 0): log("Starting " + str(num) + " progam\s", "./tmlog.txt", False) print("Starting " + str(num) + " program\s. Please wait...") self.waitForPrograms() print(str(procs) + " process\es started")
def __init__(self): """""" cmd.Cmd.__init__(self) if str(platform.system()) != "Windows": self.prompt = "\033[94mTaskmaster>\033[0m " else: self.prompt = "Taskmaster> " self.programs = list self.monitor = False log("Taskmaster object initialized", "./tmlog.txt", False)
def __init__(self, progdict): threading.Thread.__init__(self) self.stdout = None self.stderr = None self.pop = None self.progd = progdict self.tmexit = False self.name = "Thread-" + self.progd["progname"] self.active = False self.retries = 0 log("Process '" + self.name + "' initialized", "./tmlog.txt", False)
def default(self, line): '''Custom input handling''' #------------------------------------------------------------------------------# log("Input: '" + line + "'", "./tmlog.txt", False) if (line == "cheese"): ### print "Crackers" # elif line == "load": ### # self.programs = tmdata.loadConfig(os.path.realpath("./config.xml")) # print("\n---Programs Loaded---\n") elif line.startswith("monitor"): ### if not self.programs: print("Load config first!") return sc = line.split() if len(sc) == 1: for program in self.programs: program.runAndMonitor() print("\n---Monitoring " + str(len(self.programs)) + " programs---\n") else: for program in self.programs: if program.progname == sc[1]: print("\n---Monitoring " + program.progname + " ---\n") program.runAndMonitor() #check if progname is in config and if not notify user!!! elif line == "dlog": os.remove("./tmlog.txt") print("./tmlog.txt deleted!") #------------------------------------------------------------------------------# elif (line.startswith("status")): print("ALL STATUS") # splt = line.split() # if (len(splt) == 1): # log("Showing status ") ??? # showstatus() elif ( line.startswith("stop") ): #this if statement is only if programs require a specific SIGNAL to stop splt = line.split() if (len(splt) == 1): print("Please specify which program\s to stop " + "(stop all -OR- stop [program1 name] " + "[program2 name])") elif (len(splt) > 1): self.stopPrograms(splt) if (len(splt) == 2 and splt[1] == "all"): self.stopAllPrograms() elif (line.startswith("start")): print("START") else: log("Unknown command: " + line, "./tmlog.txt", True)
def monitorProcesses(self): """""" tim = threading.Timer(1.0, self.monitorProcesses) tim.start() if (self.monitor == False): tim.cancel() log("No longer monitoring processes", "./tmlog.txt", False) for prog in self.programs: if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == False): prog.processes.remove(proc) log("Removing " + proc.name, "./tmlog.txt", False)
def run(self): """""" args = self.progd["command"].split() # or shlex.split() try: self.pop = subprocess.Popen(args, stderr=subprocess.PIPE, stdout=subprocess.PIPE) except (ValueError, OSError) as e: # print("Invalid arguments given to 'subprocess.Popen'") # print("Program Name: " + self.progd["progname"]) log("Caught exception '" + str(e) + "'", "./tmlog.txt", False) return self.active = True self.monitor_timer()
def monitor(self): """Monitor the state of this process every second""" tim = threading.Timer(1.0, self.monitor) tim.start() self.pop.poll() # if (bool(self.progd["redout"]) == True): self.writeStdOut() if (bool(self.progd["rederr"]) == True): self.writeStdErr() # if (self.stop == True): tim.cancel() log("Stopping process '" + self.name + "'", "./tmlog.txt", False) self.active = False #? if (bool(self.progd["redout"]) == True): self.writeStdOut() if (bool(self.progd["rederr"]) == True): self.writeStdErr() self.stoptimeTimer() return if (self.pop.returncode != None): tim.cancel() if (bool(self.progd["redout"]) == True): self.writeStdOut() if (bool(self.progd["rederr"]) == True): self.writeStdErr() if (self.progd["restart"] == "always"): log("Process '" + self.name + "' stopped", "./tmlog.txt", False) self.run() elif (self.progd["restart"] == "unexpected"): if (self.expectedReturnCode() == False and self.retries != int(self.progd["retries"])): self.retries += 1 log("'" + self.name + "' terminated unexpectedly", "./tmlog.txt", False) self.run() log("Attempting to relaunch '" + self.name + "'", "./tmlog.txt", False) log("Retries: " + str(self.retries), "./tmlog.txt", False) else: self.active = False else: self.active = False
def loadConfig(config): """Returns a 'list()' of 'Programs' from the xml config file""" path = os.path.join(os.path.dirname(__file__), config) prog = None progs = list() xdoc = None if os.path.exists(path) and os.path.getsize(path) != 0: prog = Program() xdoc = ET.parse(path) xroot = xdoc.getroot() for xprog in xroot: prog = programFromElement(xprog) if (checkProgramCommand(prog) == True): progs.append(prog) else: log("'" + prog.progname + "' command invalid. Not loading", "./tmlog.txt", True) # progs.append(prog) return (progs)
def showStatus(self, args): """""" cnt = 1 found = False stat = "" print("") if (len(args) == 1): for prog in self.programs: print(prog.progname + ":") if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == True): stat = "Active" else: stat = "Inactive" print(proc.name + " - " + stat) print("") else: print("Not launched\n") elif (len(args) > 1): while cnt < len(args): for prog in self.programs: if (prog.progname == args[cnt]): found = True print(prog.progname + ":") if (len(prog.processes) > 0): for proc in prog.processes: if (proc.active == True): stat = "Active" else: stat = "Inactive" print(proc.name + " - " + stat) print("") else: print("Not launched\n") if (found == False): log("No program '" + args[cnt] + "' in config", "./tmlog.txt", True) found = False cnt += 1
def default(self, line): '''Custom input handling''' log("Input: '" + line + "'", "./tmlog.txt", False) if (line.startswith("status")): if (len(self.programs) < 1): print("No programs") return self.showStatus(line.split()) elif ( line.startswith("stop") ): #this if statement is only if programs require a specific SIGNAL to stop if (len(self.programs) < 1): print("No programs") return self.stopPrograms(line.split()) elif (line.startswith("start")): if (len(self.programs) < 1): print("No programs") return self.startPrograms(line.split()) elif (line.startswith("restart")): if (len(self.programs) < 1): print("No programs") return self.restartPrograms(line.split()) elif (line == "reload"): self.reloadConfig() elif (line == "-h"): self.do_help(None) elif (line.startswith("programs")): if (len(self.programs) < 1): print("No programs") return for prog in self.programs: print(prog) elif (line == "clear"): os.system("clear") else: log("Unknown command: " + line, "./tmlog.txt", True)
def run(self): """ threading.Thread.run() override. Invoked via threading.Thread.Start() """ args = self.progd["command"].split() # or shlex.split() wkdir = None envs = None log("Starting process '" + self.name + "'", "./tmlog.txt", False) if (self.progd["workingdir"]): wkdir = self.progd["workingdir"] if (len(self.progd["envvars"]) > 0): envs = self.progd["envvars"] try: self.pop = subprocess.Popen(args, cwd=wkdir, stderr=subprocess.PIPE, stdout=subprocess.PIPE, env=envs, preexec_fn=self.initializeProcess) except (ValueError, OSError) as e: print("Invalid arguments given to 'subprocess.Popen'") print("Program Name: " + self.progd["progname"]) log("Caught exception '" + str(e) + "'", "./tmlog.txt", False) return wait = self.starting or self.stopping while wait == True: wait = self.starting or self.stopping continue self.stop = False self.active = True if (int(self.progd["starttime"]) > 0): self.starttimeTimer() else: self.monitor()
def main(): """""" log("TaskMaster started", "./tmlog.txt", False) tm = Taskmaster() print("Loading programs") if str(platform.system()) != "Windows": os.system("clear") else: os.system("cls") log("Loading config file", "./tmlog.txt", False) tm.programs = tmdata.loadConfig(os.path.realpath("./config.xml")) log( str(len(tm.programs)) + " programs loaded from config", "./tmlog.txt", False) autolaunchPrograms(tm) tm.monitor = True log("Monitoring processes", "./tmlog.txt", False) tm.monitorProcesses() signal.signal(signal.SIGINT, tm.handleSigint) #!# tm.cmdloop()
def autolaunchPrograms(taskmaster): """""" cnt = 0 totnum = 0 if (len(taskmaster.programs) == 0): log("WARNING: No programs in config file", "./tmlog.txt", True) return for program in taskmaster.programs: if (program.autolaunch == True): log("Starting " + program.progname, "./tmlog.txt", False) totnum += program.runAndMonitor() cnt += 1 if (cnt > 0): print("Taskmaster is starting autolaunch programs. Please wait...") while taskmaster.programsWaiting() == True: continue log( str(totnum) + " processes (" + str(cnt) + " program\s) successfully" + " launched", "./tmlog.txt", True) else: log("No programs set to launch automatically", "./tmlog.txt", True)
def main(): """ NOTE: Nothing printed here will be visible as cmdloop clears the screen """ tm = Taskmaster() clearLog() log("TaskMaster started", "./tmlog.txt", False) os.system("clear") log("Loading config file", "./tmlog.txt", False) tm.programs = tmdata.loadConfig("./config.xml") log( str(len(tm.programs)) + " programs loaded from config", "./tmlog.txt", False) autolaunchPrograms(tm) tm.cmdloop()
def restartPrograms(self, args): """""" cnt = 1 num = 0 procs = 0 found = False if (len(args) == 1): num = len(self.programs) for prog in self.programs: if (len(prog.processes) > 0): procs += len(prog.processes) for proc in prog.processes: if (proc.active == True and proc.pop.returncode == None): proc.stop = True signum = tmfuncs.getSignalValue(prog.stopsig) proc.pop.send_signal(signum) proc.timetostart = 0 proc.run() elif (len(args) > 1): while cnt < len(args): for prog in self.programs: if (prog.progname == args[cnt]): found = True num += 1 if (len(prog.processes) > 0): procs += len(prog.processes) for proc in prog.processes: if (proc.active == True and proc.pop.returncode == None): proc.stop = True signum = tmfuncs.getSignalValue( prog.stopsig) proc.pop.send_signal(signum) proc.timetostart = 0 proc.run() if (found == False): log("No program '" + args[cnt] + "' in config", "./tmlog.txt", True) found = False cnt += 1 if (self.programsWaiting() == True): log("Restarting " + str(num) + " programs", "./tmlog.txt", False) print("Restarting " + str(num) + " programs. Please wait...") self.waitForPrograms() log(str(procs) + " processes restarted", "./tmlog.txt", True)
def autolaunchPrograms(taskmaster): """""" cnt = 0 num = 0 totnum = 0 if (len(taskmaster.programs) == 0): log("WARNING: No programs in config file", "./tmlog.txt", True) return for program in taskmaster.programs: if (program.autolaunch): while num < program.procnum: program.runAndMonitor() num += 1 totnum += num num = 0 cnt += 1 if (cnt > 0): log( str(totnum) + " processes (" + str(cnt) + " program\s) launched" + " automatically", "./tmlog.txt", True) else: log("No programs set to launch automatically", "./tmlog.txt", True)
def monitor_timer(self): tim = threading.Timer(1.0, self.monitor_timer) tim.start() self.pop.poll() if (self.tmexit == True): tim.cancel() if (self.is_alive()): self.pop.send_signal( tmfuncs.getSignalValue(self.progd["stopsig"])) log("Terminating '" + self.name + "'", "./tmlog.txt", False) self.active = False return if (self.pop.returncode != None): tim.cancel() if (self.progd["restart"] == "always"): self.run() log("Restarting '" + self.name + "'", "./tmlog.txt", False) elif (self.progd["restart"] == "unexpected"): if (self.expectedReturnCode() == False and self.retries != self.progd["retries"]): self.retries += 1 log("'" + self.name + "' terminated unexpectedly", "./tmlog.txt", False) self.run() log("Attempting to relaunch '" + self.name + "'", "./tmlog.txt", False) log("Retries: " + str(self.retries)) else: self.active = False else: log(self.name + " stopped", "./tmlog.txt", False) self.active = False
def __init__(self, args=None): """""" self.progname = "TMProg" self.command = "" self.procnum = 1 self.autolaunch = False self.starttime = 5 self.restart = "never" self.retries = 3 self.stopsig = "SIG" self.stoptime = 10 self.exitcode = [0] self.envvars = dict self.workingdir = "./" self.umask = 022 self.stdout = self.workingdir + self.progname + ".tm.stdout" self.stderr = self.workingdir + self.progname + ".tm.stderr" self.redout = False self.rederr = False self.processes = list() # print("UMASK: " + format(self.umask, "03o")) if type(args) is dict: for key, val in args.iteritems(): if key == "progname": self.progname = val elif key == "command": self.command = val elif key == "procnum": self.procnum = val elif key == "autolaunch": self.autolaunch = val elif key == "starttime": self.starttime = val elif key == "restart": self.restart = val elif key == "retries": self.retries = val elif key == "stopsig": self.stopsig = val elif key == "stoptime": self.stoptime = val elif type(val) is list and key == "exitcodes": self.exitcodes = list() for i in val: self.exitcodes.append(i) elif key == "stdout": self.stdout = val elif key == "stderr": self.stderr = val elif key == "redout": self.redout = val elif key == "rederr": self.rederr = val elif type(val) is dict and key == "envvars": self.envvars = dict() for k, v in val.iteritems(): self.envvars[k] = v elif key == "workingdir": self.workingdir = val elif key == "umask": self.umask = val log("Program '" + self.progname + "' initialized", "./tmlog.txt", False)
def handleSighup(self, signum, frame): """""" if (signum == signal.SIGHUP): log("Caught SIGHUP", "./tmlog.txt", False) self.default("reload")
def do_exit(self, args): '''Exits the Taskmaster shell when user inputs "exit"''' if (len(self.programs) > 0): self.stopPrograms(["stop", "all"]) log("TaskMaster exiting", "./tmlog.txt", True) exit(0)
def reloadConfig(self): """""" cnt = 0 rmcnt = 0 chcnt = 0 chprogs = list() allnewprogs = list() toremove = list() allconfig = tmdata.loadConfig("./config.xml") newprogs = tmdata.loadNewPrograms("./config.xml", self.programs) stopstring = "stop" startstring = "start" # removes all programs from 'self.programs' that are no longer present # in the config file for prog in self.programs: if (tmdata.programExists(prog, "./config.xml") == False): rmcnt += 1 toremove.append(prog) # this loop checks if a program's variables have changed, and if so, # adds a new Program with changed variables to 'chprogs' for prog in self.programs: chprog = tmfuncs.programChanged(allconfig, prog) if not (chprog == None): chcnt += 1 toremove.append(prog) chprogs.append(chprog) # ensure some sort of change ocurred if (rmcnt == 0 and chcnt == 0 and len(newprogs) == 0): print("No changes to config.") return # log the change\s if (len(newprogs) > 0): log( str(len(newprogs)) + " new programs added to config", "./tmlog.txt", True) if (chcnt > 0): log( str(chcnt) + " programs changed in config", "./tmlog.txt", True) if (rmcnt > 0): log( str(rmcnt) + " programs removed from config", "./tmlog.txt", True) # stop programs in 'self.programs' that exist in 'toremove' for prog in self.programs: for rprog in toremove: # if (rprog == prog): if (rprog.progname == prog.progname): if (prog.hasActiveProcesses() == True): cnt += 1 stopstring += " " + prog.progname # stop runnuing processes # print("Reloading config file...") log("Reloading config file...", "./tmlog.txt", True) if (cnt > 0): self.default(stopstring) self.waitForPrograms() cnt = 0 # remove programs in 'self.programs' that exist in 'toremove' for rprog in toremove: for prog in self.programs: if (prog.progname == rprog.progname): self.programs.remove(prog) # adds all changed programs to 'allnewprogs' for prog in chprogs: allnewprogs.append(prog) # adds all new programs to 'allnewprogs' for prog in newprogs: allnewprogs.append(prog) # adds programs from 'allnewprogs' to 'self.programs' and starts them # if applicable for prog in allnewprogs: self.programs.append(prog) if (prog.autolaunch == True): startstring += " " + prog.progname cnt += 1 if (cnt > 0): self.default(startstring) self.waitForPrograms()