#-*-Coding:utf-8-*-import osimport subprocessimport signalclass Mocklogger (object): "' Simulation log class. Easy unit Testing. "Def __init__ (self): Self.info = Self.error = self.critical = Self.debug def debug (Self, msg): Prin T "__logger__:" +msg class Shell (object): ' completes the shell script wrapper. Run () is a normal call and waits for the shell command to return. Run_background () is an asynchronous call that returns immediately without waiting for the shell command to complete an asynchronous call, either using the Get_status () query state, or using wait () to enter the blocking state, waiting for the shell to finish. When calling asynchronously, using Kill () to stop the script, you still need to wait for a real exit using wait (). TODO does not verify the case when the shell command contains a very large result output. ' Def __init__ (self, cmd): self.cmd = cmd # cmd includes commands and parameters Self.ret_code = None Self.ret_info = Non E self.err_info = None #使用时可替换为具体的logger Self.logger = Mocklogger () def run_background (SE LF): "" Executes the shell command in a non-blocking manner (the default for Popen). "' Self.logger.debug (" Run%s "%self.cmd) # Popen throws a OSError exception when the command to execute does not exist, but after Shell=true, the # Shell handles the command does not exist Error, so there is no oserror exception, so we do not have to deal with self._process = subprocess. Popen (SELF.CMD, Shell=true, stdout=subprocess. PIPE, Stderr=subprocess. PIPE) #非阻塞 def run (self): "" Executes the shell command in a blocking manner. "' Self.run_background () self.wait () def wait (self):" Waits for shell execution to complete. "' Self.logger.debug (" waiting%s "%self.cmd) self.ret_info, self.err_info = Self._process.communicate () #阻塞 # returncode:a Negative value-n indicates that the child is # terminated by signal N Self.ret_cod E = Self._process.returncode self.logger.debug ("Waiting%s done. Return code is%d "% (Self.cmd, Self.ret_code)) def get_status (self):" Gets the script run state (Runn Ing| Finished) "Retcode = Self._process.poll () if Retcode = = None:status =" RUNNING " Else:status = "Finished" Self.logger.debug ("%s status is%s"% (Self.cmd, status)) return status # Python2.4 's subprocess ain't Send_signal,terminate,kill # So here's a cottage, 2.7 can be used directly with Self._process Kill () def send_signal (self, SIG): Self.logger.debug ("Send signal%s to%s"% (SIG, self.cm d) Os.kill (Self._process.pid, SIG) def terminate (self): self.send_signal (signal. SIGTERM) def Kill (self): self.send_signal (signal. SIGKILL) If __name__ = = "__main__": ' ' Test Code ' ' # 1. Test normal SA = Shell (' Who ') Sa.run () print "Return code:", Sa.ret_code print "return info:", Sa.ret_info # 2. Test stderr sb = Shell (' ls/export/dir_should_not_exists ') sb.run () print "Return code:", Sb.ret_code print "R Eturn info: ", sb.ret_info print" Error info: ", Sb.err_info # 3. Test background sc = Shell (' Sleep 2 ') Sc.run_background () print ' warmly hello from parent process ' print ' Retu RN code: ", Sc.ret_code print" Status: ", Sc.get_status () sc.wait () print" Return code: ", Sc.ret_code print" ret Urn Info: ", Sc.ret_info # 4. Test Kill import Time SD = Shell (' Sleep 2 ') Sd.run_background () time.sleep (1) Sd.kill () sd.wait () # NOTE, still need to wait print sd.ret_code print s D.ret_info # 5. Test multiple command and uncompleted command output SE = Shell (' pwd;sleep 1;pwd;pwd ') se.run_background () time.s Leep (1) Se.kill () se.wait () # NOTE, still need to wait print se.ret_code print Se.ret_info # 6. Test wrong command SF = Shell (' aaaaa ') sf.run () Print sf.ret_code print sf.ret_info print Sf.err_info
[Python recipes] Python calls the shell command to get the return value and return information