国产片侵犯亲女视频播放_亚洲精品二区_在线免费国产视频_欧美精品一区二区三区在线_少妇久久久_在线观看av不卡

腳本之家,腳本語言編程技術及教程分享平臺!
分類導航

Python|VBS|Ruby|Lua|perl|VBA|Golang|PowerShell|Erlang|autoit|Dos|bat|

服務器之家 - 腳本之家 - Python - Python封裝shell命令實例分析

Python封裝shell命令實例分析

2020-06-22 09:35鴣斑兔 Python

這篇文章主要介紹了Python封裝shell命令,實例分析了Python將各種常用shell命令封裝進一個類中以便調用的方法,非常具有實用價值,需要的朋友可以參考下

本文實例講述了Python封裝shell命令的方法。分享給大家供大家參考。具體實現方法如下:

?
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):
  '''模擬日志類。方便單元測試。'''
  def __init__(self):
    self.info = self.error = self.critical = self.debug
  def debug(self, msg):
    print "LOGGER:"+msg
class Shell(object):
  '''完成Shell腳本的包裝。
  執行結果存放在Shell.ret_code, Shell.ret_info, Shell.err_info中
  run()為普通調用,會等待shell命令返回。
  run_background()為異步調用,會立刻返回,不等待shell命令完成
  異步調用時,可以使用get_status()查詢狀態,或使用wait()進入阻塞狀態,
  等待shell執行完成。
  異步調用時,使用kill()強行停止腳本后,仍然需要使用wait()等待真正退出。
  TODO 未驗證Shell命令含有超大結果輸出時的情況。
  '''
  def __init__(self, cmd):
    self.cmd = cmd # cmd包括命令和參數
    self.ret_code = None
    self.ret_info = None
    self.err_info = None
    #使用時可替換為具體的logger
    self.logger = MockLogger()
  def run_background(self):
    '''以非阻塞方式執行shell命令(Popen的默認方式)。
    '''
    self.logger.debug("run %s"%self.cmd)
    # Popen在要執行的命令不存在時會拋出OSError異常,但shell=True后,
    # shell會處理命令不存在的錯誤,因此沒有了OSError異常,故不用處理
    self._process = subprocess.Popen(self.cmd, shell=True,
        stdout=subprocess.PIPE, stderr=subprocess.PIPE) #非阻塞
  def run(self):
    '''以阻塞方式執行shell命令。
    '''
    self.run_background()
    self.wait()
  def run_cmd(self, cmd):
    '''直接執行某條命令。方便一個實例重復使用執行多條命令。
    '''
    self.cmd = cmd
    self.run()
  def wait(self):
    '''等待shell執行完成。
    '''
    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 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):
    '''獲取腳本運行狀態(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還沒有send_signal,terminate,kill
  # 所以這里要山寨一把,2.7可直接用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_info
class RemoteShell(Shell):
  '''遠程執行命令(ssh方式)。
  XXX 含特殊字符的命令可能導致調用失效,如雙引號,美元號$
  NOTE 若cmd含有雙引號,可使用RemoteShell2
  '''
  def __init__(self, cmd, ip):
    ssh = ("ssh -o PreferredAuthentications=publickey -o "
        "StrictHostKeyChecking=no -o ConnectTimeout=10")
    # 不必檢查IP有效性,也不必檢查信任關系,有問題shell會報錯
    cmd = '%s %s "%s"'%(ssh, ip, cmd)
    Shell.__init__(self, cmd)
class RemoteShell2(RemoteShell):
  '''與RemoteShell相同,只是變換了引號。
  '''
  def __init__(self, cmd, ip):
    RemoteShell.__init__(self, cmd, ip)
    self.cmd = "%s %s '%s'"%(ssh, ip, cmd)
class SuShell(Shell):
  '''切換用戶執行命令(su方式)。
  XXX 只適合使用root切換至其它用戶。
    因為其它切換用戶后需要輸入密碼,這樣程序會掛住。
  XXX 含特殊字符的命令可能導致調用失效,如雙引號,美元號$
  NOTE 若cmd含有雙引號,可使用SuShell2
  '''
  def __init__(self, cmd, user):
    if os.getuid() != 0: # 非root用戶直接報錯
      raise Exception('SuShell must be called by root user!')
    cmd = 'su - %s -c "%s"'%(user, cmd)
    Shell.__init__(self, cmd)
class SuShell2(SuShell):
  '''與SuShell相同,只是變換了引號。
  '''
  def __init__(self, cmd, user):
    SuShell.__init__(self, cmd, user)
    self.cmd = "su - %s -c '%s'"%(user, cmd)
class SuShellDeprecated(Shell):
  '''切換用戶執行命令(setuid方式)。
  執行的函數為run2,而不是run
  XXX 以“不干凈”的方式運行:僅切換用戶和組,環境變量信息不變。
  XXX 無法獲取命令的ret_code, ret_info, err_info
  XXX 只適合使用root切換至其它用戶。
  '''
  def __init__(self, cmd, user):
    self.user = user
    Shell.__init__(self, cmd)
  def run2(self):
    if os.getuid() != 0: # 非root用戶直接報錯
      raise Exception('SuShell2 must be called by root user!')
    child_pid = os.fork()
    if child_pid == 0: # 子進程干活
      uid, gid = pwd.getpwnam(self.user)[2:4]
      os.setgid(gid) # 必須先設置組
      os.setuid(uid)
      self.run()
      sys.exit(0) # 子進程退出,防止繼續執行其它代碼
    else: # 父進程等待子進程退出
      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', '127.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', '1711.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()

希望本文所述對大家的Python程序設計有所幫助。

延伸 · 閱讀

精彩推薦
Weibo Article 1 Weibo Article 2 Weibo Article 3 Weibo Article 4 Weibo Article 5 Weibo Article 6 Weibo Article 7 Weibo Article 8 Weibo Article 9 Weibo Article 10 Weibo Article 11 Weibo Article 12 Weibo Article 13 Weibo Article 14 Weibo Article 15 Weibo Article 16 Weibo Article 17 Weibo Article 18 Weibo Article 19 Weibo Article 20 Weibo Article 21 Weibo Article 22 Weibo Article 23 Weibo Article 24 Weibo Article 25 Weibo Article 26 Weibo Article 27 Weibo Article 28 Weibo Article 29 Weibo Article 30 Weibo Article 31 Weibo Article 32 Weibo Article 33 Weibo Article 34 Weibo Article 35 Weibo Article 36 Weibo Article 37 Weibo Article 38 Weibo Article 39 Weibo Article 40
主站蜘蛛池模板: 欧美成人二区 | 日韩一区二区三区在线观看 | 欧美日韩一区二区三区在线观看 | 婷婷激情综合 | 成年人黄色影院 | 国产va | 久久久影院 | 久久久久国产精品 | 亚洲精品在线视频 | 北条麻妃一区二区三区在线观看 | 夜夜骚av | 一级毛片免费视频 | 性一区 | 日韩电影在线 | 91av在线免费观看 | 精品国产乱码久久久久久影片 | 亚洲自拍偷拍一区 | 日美毛片 | www.国产区 | 色婷婷一二三 | 91社影院在线观看 | 免费在线观看黄色 | 精品一区二区三区在线视频 | 99视频在线免费观看 | 久久久人成影片免费观看 | 午夜视频在线免费观看 | 国产精品久久精品 | 久久精品国产v日韩v亚洲 | 国产精品视频导航 | 中文字幕日韩有码 | 91久久国产精品 | 日韩高清在线一区 | 成人在线午夜 | 免费在线观看黄色 | 久久久99国产精品免费 | 亚洲电影天堂在线观看 | 在线看一区 | 日韩一区电影 | 日日操操 | 成人精品福利视频 | 中文字幕在线观看一区二区三区 |