Python Encapsulation shell Command Instance analysis

Source: Internet
Author: User
The example in this article describes how Python encapsulates shell commands. Share to everyone for your reference. The implementation method is as follows:

#-*-Coding:utf-8-*-import osimport subprocessimport signalimport pwdimport sysclass MockLogger (object): "' Simulation log class. Easy unit Testing. "Def __init__ (self): Self.info = Self.error = self.critical = Self.debug def debug (Self, msg): print" LOGGER: "+  Msgclass Shell (object): ' Finish wrapping the shell script.  Execution results are stored in Shell.ret_code, Shell.ret_info, Shell.err_info, and run () is a normal call that 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 = None Self.err_i NFO = None #使用时可替换为具体的logger Self.logger = Mocklogger () def run_background (self): "" Executes the shell command in a non-blocking manner (the default way of Popen)    。 ' ' ' Self.logger.debug ("Run%s"%self.cmd) # Popen throws a OSError exception when the command to be executed does not exist, but after Shell=true, the # Shell handles the error that the command does not exist, so there is no OSE Rror exception, so 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 run_cmd (self, cmd):" ' executes a command directly.    Facilitates repeated use of one instance to execute multiple commands.    "' Self.cmd = cmd self.run () 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 () #阻塞 # RET Urncode:a negative value-n indicates that the child is # terminated by signal N Self.ret_code = Self._process.ret Urncode self.logger.debug ("Waiting%s done. Return code is%d "% (Self.cmd, Self.ret_code)) def get_status (self):" Gets the script run state (running| 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 subprocess not yet Send_signa L,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.cmd)) Os.kill (Self._process.pid, SIG) def-Terminate (self): self. Send_signal (signal. SIGTERM) def Kill (self): self.send_signal (signal.  SIGKILL) def print_result (self): print "Return code:", Self.ret_code print "return info:", self.ret_info print "  Error info: ", Self.err_infoclass Remoteshell (Shell): ' Remote execute command (SSH mode). XXX commands with special characters can cause a call to fail, such as double quotes, USD $ NOTE If cmd contains double quotes, use REMOTESHELL2 ' Def __init__ (self, cmd, IP): SSH = ("Ssh-o Prefer Redauthentications=publickey-o "" Stricthostkeychecking=no-o connecttimeout=10 ") # no need to check for IP validity or to check for trust relationships, there is a problem shel L will error cmd = '%s '%s '%s '% (SSH, IP, cmd) shell.__init__ (self, CMD) class RemoteShell2 (Remoteshell): "' Same as Remoteshell,  Just change the quotation marks. "Def __init__ (self, cmd, IP): remoteshell.__init__ (self, cmd, IP) self.cmd ="%s%s '%s ' "% (SSH, IP, cmd) class Su  Shell: "Switch User execution command (SU mode)."    XXX is only suitable for using root to switch to other users.  Because the other user needs to enter the password after switching, so the program will hang. XXX commands with special characters can cause a call to fail, such as double quotes,USD $ NOTE If cmd contains double quotes, you can use SUSHELL2 "Def __init__ (self, cmd, user): If Os.getuid ()! = 0: # non-root user direct error raise EXC    Eption (' Sushell must is called by Root user! ')  cmd = ' Su-%s-c '%s '% (user, cmd) shell.__init__ (self, CMD) class SuShell2 (Sushell): ' ' is the same as Sushell, just transforms the quotation marks. ' Def __init__ (self, cmd, user): Sushell.__init__ (self, cmd, user) Self.cmd = "Su-%s-c '%s '"% (user, CMD) class  Sushelldeprecated (Shell): "Switch User execution command (setuid mode).  The function executed is run2, not run XXX, which runs "dirty": Switches users and groups only, and the environment variable information does not change.  XXX cannot get command of Ret_code, ret_info, err_info xxx is only suitable for using root to switch to other users.  ' Def __init__ (self, cmd, user): Self.user = user shell.__init__ (self, cmd) def run2 (self): if Os.getuid ()! =    0: # Non-root user direct error raise Exception (' SuShell2 must be called by Root user! ') Child_pid = Os.fork () if child_pid = = 0: # sub-process work uid, GID = Pwd.getpwnam (self.user) [2:4] Os.setgid (GID) # must first Set group Os.setuid (UID) self.run () sys.exit (0) # Child process exits to prevent execution of other code else: # Parent process waits for child process fallbackOut Os.waitpid (child_pid, 0) If __name__ = = "__main__": ' ' Test code ' # 1. Test normal SA = Shell (' Who ') Sa.run () Sa.print_result () # 2. Test stderr sb = Shell (' ls/export/dir_should_not_exists ') Sb.run () Sb.print_result () # 3. Test background sc = Shell (' Sleep 1 ') Sc.run_background () print ' Hello from parent process ' print ' Return code: ", SC.R Et_code print "Status:", Sc.get_status () sc.wait () Sc.print_result () # 4.  Test Kill import Time SD = Shell (' Sleep 2 ') Sd.run_background () time.sleep (1) Sd.kill () sd.wait () # NOTE, still need To wait Sd.print_result () # 5. Test multiple command and uncompleted command output SE = Shell (' pwd;sleep 1;pwd;pwd ') se.run_background () Time.sleep (1 ) Se.kill () se.wait () # NOTE, still need to wait Se.print_result () # 6. Test wrong command SF = Shell (' aaaaa ') Sf.run () Sf.print_result () # 7. Test instance reuse to run other command sf.cmd = ' echo aaaaa ' Sf.run () sf.print_result () sg = Remoteshell (' pwd ', ' 127 .0.0.1 ') Sg.run () Sg.print_result () # unreachable IP SG2 = Remoteshell (' pwd ', ' 17.0.0.1 ') Sg2.run () Sg2.print_result () # I Nvalid IP sg3 = Remoteshell (' pwd ', ' 1711.0.0.1 ') Sg3.run () Sg3.print_result () # IP without trust relation SG3 = Remot Eshell (' pwd ', ' 10.145.132.247 ') Sg3.run () sg3.print_result () sh = Sushell (' pwd ', ' Ossuser ') Sh.run () Sh.print_result (  # wrong user Si = Sushell (' pwd ', ' ossuser123 ') Si.run () Si.print_result () # user need password si = Sushell (' pwd ', ' Root ') Si.run () Si.print_result ()

Hopefully this article will help you with Python programming.

  • Contact Us

    The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

    If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

    A Free Trial That Lets You Build Big!

    Start building with 50+ products and up to 12 months usage for Elastic Compute Service

    • Sales Support

      1 on 1 presale consultation

    • After-Sales Support

      24/7 Technical Support 6 Free Tickets per Quarter Faster Response

    • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.