Python shell command instance analysis

Source: Internet
Author: User

Python shell command instance analysis

This example describes how to encapsulate shell commands in Python. Share it with you for your reference. The specific implementation method is as follows:

?

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

93

94

95

96

97

98

99

100

101

102

103

104

105

106

107

108

109

110

111

112

113

114

115

116

117

118

119

120

121

122

123

124

125

126

127

128

129

130

131

132

133

134

135

136

137

138

139

140

141

142

143

144

145

146

147

148

149

150

151

152

153

154

155

156

157

158

159

160

161

162

163

164

165

166

167

168

169

170

171

172

173

174

175

176

177

178

179

180

181

182

183

184

185

186

187

188

189

190

191

192

193

194

195

196

197

198

199

200

201

202

203

204

#-*-Coding: UTF-8 -*-

Import OS

Import subprocess

Import signal

Import pwd

Import sys

Class MockLogger (object ):

''' Simulate the log class. Facilitate unit testing. '''

Def _ init _ (self ):

Self.info = self. error = self. critical = self. debug

Def debug (self, msg ):

Print "LOGGER:" + msg

Class Shell (object ):

'''To wrap the Shell script.

The execution results are stored in Shell. ret_code, Shell. ret_info, and Shell. err_info.

Run () is a normal call and will wait for the shell command to return.

Run_background () is an asynchronous call and will return immediately without waiting for the completion of the shell command

During asynchronous calling, you can use get_status () to query the status, or use wait () to enter the blocking status,

Wait until the shell execution is complete.

After you use kill () to forcibly stop the script during asynchronous calling, you still need to use wait () to wait for the script to exit.

TODO does not verify that Shell commands contain ultra-large output results.

'''

Def _ init _ (self, cmd ):

Self. cmd = cmd # cmd includes commands and Parameters

Self. ret_code = None

Self. ret_info = None

Self. err_info = None

# You can replace it with a specific logger.

Self. logger = MockLogger ()

Def run_background (self ):

''' Execute the shell command in non-blocking mode (default mode of Popen ).

'''

Self. logger. debug ("run % s" % self. cmd)

# Popen will throw an OSError exception when the command to be executed does not exist, but after shell = True,

# Shell will handle errors that do not exist in the command, so there is no OSError exception, so you do not need to handle it

Self. _ process = subprocess. Popen (self. cmd, shell = True,

Stdout = subprocess. PIPE, stderr = subprocess. PIPE) # non-blocking

Def run (self ):

''' Execute shell commands in blocking mode.

'''

Self. run_background ()

Self. wait ()

Def run_cmd (self, cmd ):

''' Directly executes a command. It is convenient for one instance to execute multiple commands repeatedly.

'''

Self. cmd = cmd

Self. run ()

Def wait (self ):

'''Wait until shell execution is complete.

'''

Self. logger. debug ("waiting % s" % self. cmd)

Self. ret_info, self. err_info = self. _ process. communicate () # Blocking

# Returncode: A negative value-N indicates that the child was

# Terminated by signal N

Self. ret_code = self. _ process. returncode

Self. logger. debug ("waiting % s done. return code is % d" % (self. cmd,

Self. ret_code ))

Def get_status (self ):

''' Get the script RUNNING status (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

# The subprocess of Python2.4 does not have send_signal, terminate, or kill

# So here we need to copy one. 2.7 can be used directly with the kill () of self. _ process ()

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_info

Class RemoteShell (Shell ):

''' Remote command execution (ssh ).

XXX commands with special characters may cause invalid calls, such as double quotation marks and dollar signs $

NOTE if cmd contains double quotation marks, you can use RemoteShell2

'''

Def _ init _ (self, cmd, ip ):

Ssh = ("ssh-o PreferredAuthentications = publickey-o"

"StrictHostKeyChecking = no-o ConnectTimeout = 10 ")

# Check whether the IP address is valid or the trust relationship is not required. If there is a problem, shell reports an error.

Cmd = '% s "% s"' % (ssh, ip, cmd)

Shell. _ init _ (self, cmd)

Class RemoteShell2 (RemoteShell ):

''' Is the same as RemoteShell, but the quotation marks are changed.

'''

Def _ init _ (self, cmd, ip ):

RemoteShell. _ init _ (self, cmd, ip)

Self. cmd = "% s '% S'" % (ssh, ip, cmd)

Class SuShell (Shell ):

''' Switch the user to execute the command (su mode ).

XXX is only applicable to switching from root to other users.

Because other users need to enter the password after switching, the program will be suspended.

XXX commands with special characters may cause invalid calls, such as double quotation marks and dollar signs $

NOTE if cmd contains double quotation marks, you can use SuShell2

'''

Def _ init _ (self, cmd, user ):

If OS. getuid ()! = 0: # direct Error Reporting for non-root users

Raise Exception ('sushell must be called by root user! ')

Cmd = 'Su-% s-c "% s" '% (user, cmd)

Shell. _ init _ (self, cmd)

Class SuShell2 (SuShell ):

''' Is the same as SuShell, but the quotation marks are changed.

'''

Def _ init _ (self, cmd, user ):

SuShell. _ init _ (self, cmd, user)

Self. cmd = "su-% s-c '% S'" % (user, cmd)

Class SuShellDeprecated (Shell ):

''' Switch the user to execute the command (in the setuid mode ).

The executed function is run2, not run.

XXX runs in "not clean" Mode: only users and groups are switched, and the environment variable information remains unchanged.

XXX cannot obtain the ret_code, ret_info, and err_info of the command.

XXX is only applicable to switching from root to other users.

'''

Def _ init _ (self, cmd, user ):

Self. user = user

Shell. _ init _ (self, cmd)

Def run2 (self ):

If OS. getuid ()! = 0: # direct Error Reporting for non-root users

Raise Exception ('sushell2 must be called by root user! ')

Child_pid = OS. fork ()

If child_pid = 0: # subprocesses work

Uid, gid = pwd. getpwnam (self. user) [2: 4]

OS. setgid (gid) # You must set the Group first.

OS. setuid (uid)

Self. run ()

Sys. exit (0) # The sub-process exits to prevent other code from being executed.

Else: # The parent process waits for the child process to exit

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. ret_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', '2017. 0.0.1 ')

Sg. run ()

Sg. print_result ()

# Unreachable ip

Sg2 = RemoteShell ('pwd', '17. 0.0.1 ')

Sg2.run ()

Sg2.print _ result ()

# Invalid ip

Sg3 = RemoteShell ('pwd', '2017. 0.0.1 ')

Sg3.run ()

Sg3.print _ result ()

# Ip without trust relation

Sg3 = RemoteShell ('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 ()

I hope 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.