forked from andaok/python
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathThreadExam1.py
More file actions
202 lines (147 loc) · 5.3 KB
/
ThreadExam1.py
File metadata and controls
202 lines (147 loc) · 5.3 KB
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
# -*- encoding:utf-8 -*-
'''
Created on Jun 9, 2012
@author: wye
'''
"""
对发出的命令进行控制:失败重试,超时kill,控制该命令stdin,stdout,stderr.
"""
import os
import sys
import time
import stat
import signal
import struct
import fcntl
import socket
import commands
import logging
try:
from threading import Thread
except ImportError:
from dummy_threading import Thread
# not using subprocess package to maintain at least python 2.3 compat.
from popen2 import Popen3
#local imports
#from ctx_exceptions import UnexpectedError, IncompatibleEnvironment
#from ctx_logging import getlog
def getlog(logfile="/tmp/log.log"):
logger = logging.Logger("logrecord")
hdlr = logging.FileHandler(logfile)
formatter = logging.Formatter("%(asctime)s -- %(levelname)s -- %(message)s")
hdlr.setFormatter(formatter)
logger.addHandler(hdlr)
logger.setLevel(logging.NOTSET)
return logger
class SimpleRunThread(Thread):
"""Run a command with timeout options, delay, stdin, etc."""
def __init__(self, cmd, killsig=-1, killtime=0, stdin=None, delay=None, log_override=None):
"""Populate the thread.
Required parameters:
* cmd -- command to run
Keyword parameters:
* killsig -- signum to kill with, default is unset
(needed if you set a killtime)
* killtime -- secs (float or int) to wait before kill, default is
unset (if set, needs killsig parameter)
* stdin -- optional stdin to push, default is unset
* delay -- secs (float or int) to wait before invoking cmd
Properties available:
* stdout -- stdout data or None
* stderr -- stderr data or None
* killed -- boolean, set True if cmd was killed
* exception -- if kill won't work
"""
Thread.__init__(self)
self.cmd = cmd
self.stdin = stdin
self.killsig = killsig
self.killtime = float(killtime)
self.delay = delay
self.exception = None
self.exit = None
self.stdout = None
self.stderr = None
self.killed = False
self.log = getlog()
def run(self):
if self.delay:
self.log.debug("delaying for %.3f secs: '%s'" % (self.delay, self.cmd))
time.sleep(self.delay)
self.log.debug("program starting '%s'" % self.cmd)
p = Popen3(self.cmd, True)
print p.pid
if self.stdin:
if p.poll() == -1:
p.tochild.write(self.stdin)
p.tochild.flush()
p.tochild.close()
#log.debug("wrote '%s' to child" % self.stdin)
else:
self.log.error("child exited before stdin was written to")
done = False
while not done and self.killtime > 0:
time.sleep(0.2)
if p.poll() != -1:
done = True
self.killtime -= 0.2
if not done and self.killsig != -1:
try:
os.kill(p.pid, self.killsig)
self.killed = True
except OSError, e:
self.log.exception("problem killing")
self.exception = e
return
status = p.wait()
if os.WIFSIGNALED(status):
self.exit = "SIGNAL: " + str(os.WTERMSIG(status))
elif os.WIFEXITED(status):
self.exit = str(os.WEXITSTATUS(status))
else:
self.exit = "UNKNOWN"
self.stdout = p.fromchild.read()
self.stderr = p.childerr.read()
p.fromchild.close()
p.childerr.close()
self.log.debug("program ended: '%s'" % self.cmd)
def runexe(cmd, killtime=2.0, retry=0):
"""Run a system program.
Required parameter:
* cmd -- command to run, string
* retry -- how many retry we will do when the exit status is non-zero
Default is 0.
Keyword parameter:
* killtime -- how many seconds to wait before SIGKILL (int or float)
Default is 2.0 seconds.
Return (exitcode, stdout, stderr)
* exitcode -- string exit code or msg
* stdout -- stdout or None
* stderr -- stderr or None
Raises IncompatibleEnvironment for serious issue (but not on non-zero exit)
"""
for i in range(retry+1):
if killtime > 0:
thr = SimpleRunThread(cmd, killsig=signal.SIGKILL, killtime=killtime)
else:
thr = SimpleRunThread(cmd)
thr.start()
thr.join()
# sudo child won't take signals
if thr.exception:
#raise IncompatibleEnvironment(str(thr.exception))
raise Exception(str(thr.exception))
if thr.exit == "0":
break
else:
time.sleep(0.5)
return (thr.exit, thr.stdout, thr.stderr)
#################
#MAIN
#################
if __name__ == "__main__":
(exitcode,stdout,stderr) = runexe("ls -al /var/data/github")
logger = getlog()
logger.debug("program exit code : %s"%exitcode)
logger.debug("program stdout : %s"%stdout)
logger.debug("program stderr : %s"%stderr)