7 class ExceptionTimeout(Exception): pass
8 class ExceptionReadTimeout(Exception): pass
10 ssh_options = { 'StrictHostKeyChecking':'no',
12 'PasswordAuthentication':'no',
13 'ConnectTimeout':'%s' % COMMAND_TIMEOUT}
14 from select import select
18 class Sopen(subprocess.Popen):
19 def kill(self, sig = signal.SIGTERM):
21 # NOTE: this also kills parent... so doesn't work like I want.
22 # NOTE: adding 'exec' before the cmd removes the extra sh, and
23 # partially addresses this problem.
24 #os.killpg(os.getpgid(self.pid), signal.SIGKILL)
25 os.kill(self.pid, sig)
27 # no such process, due to it already exiting...
31 def read_t(stream, count=1, timeout=COMMAND_TIMEOUT*2):
36 lin, lout, lerr = select([stream], [], [], timeout)
39 raise ExceptionReadTimeout("TIMEOUT reading from command")
42 outbytes = stream.read(count)
44 print 'no content yet.'
46 # the select timeout should catch this.
55 lin, lout, lerr = select([stream], [], [], timeout)
57 raise ExceptionReadTimeout("TIMEOUT reading from command")
59 return stream.read(count)
65 def run_noexcept(self, cmd, timeout=COMMAND_TIMEOUT*2):
68 return CMD.run(self,cmd,timeout)
69 except ExceptionTimeout:
70 import traceback; print traceback.print_exc()
71 return ("", "ScriptTimeout")
72 except ExceptionReadTimeout:
74 print traceback.print_exc()
75 return ("", "RunningScriptTimeout")
76 except Exception, err:
77 from nodecommon import email_exception
81 def system(self, cmd, timeout=COMMAND_TIMEOUT*2):
82 (o,e) = self.run(cmd, timeout)
85 if self.s.returncode is None:
87 return self.s.returncode
89 def run(self, cmd, timeout=COMMAND_TIMEOUT*2):
91 print "CMD.run(%s)" % cmd
92 s = Sopen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
94 (f_in, f_out, f_err) = (s.stdin, s.stdout, s.stderr)
95 lout, lin, lerr = select([f_out], [], [f_err], timeout)
96 if len(lin) == 0 and len(lout) == 0 and len(lerr) == 0:
97 # Reached a timeout! Nuke process so it does not hang.
98 print "TIMEOUT!!!!!!!!!!!!!!!!!!!"
99 s.kill(signal.SIGKILL)
100 raise ExceptionTimeout("TIMEOUT Running: %s" % cmd)
103 #print len(lin), len(lout), len(lerr)
109 #print "reading from f_out"
110 #if len(lout) > 0: o_value = f_out.read()
111 #print "reading from f_err"
112 #if len(lerr) > 0: e_value = f_err.read()
113 #o_value = f_out.read()
114 flags = fcntl.fcntl(f_out, fcntl.F_GETFL)
115 fcntl.fcntl(f_out, fcntl.F_SETFL, flags | os.O_NONBLOCK)
118 o_value = read_t(f_out,1,30)
119 except ExceptionReadTimeout:
120 s.kill(signal.SIGKILL)
121 raise ExceptionReadTimeout("TIMEOUT: failed to read from cmd: %s" % cmd)
123 e_value = f_err.read()
125 o_value = o_value.strip()
126 e_value = e_value.strip()
131 s.kill(signal.SIGKILL)
133 return (o_value, e_value)
135 def runargs(self, args, timeout=COMMAND_TIMEOUT*2):
137 #print "CMD.run(%s)" % " ".join(args)
138 s = Sopen(args, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
140 (f_in, f_out, f_err) = (s.stdin, s.stdout, s.stderr)
141 lout, lin, lerr = select([f_out], [], [f_err], timeout)
142 if len(lin) == 0 and len(lout) == 0 and len(lerr) == 0:
143 # Reached a timeout! Nuke process so it does not hang.
144 s.kill(signal.SIGKILL)
145 raise ExceptionTimeout("TIMEOUT Running: %s" % cmd)
146 o_value = f_out.read()
148 if o_value == "": # An error has occured
149 e_value = f_err.read()
151 o_value = o_value.strip()
152 e_value = e_value.strip()
157 s.kill(signal.SIGKILL)
159 return (o_value, e_value)
163 def __init__(self, user, host, port=22, options = ssh_options):
164 self.options = options
170 def __options_to_str(self):
172 for o,v in self.options.iteritems():
173 options = options + "-o %s=%s " % (o,v)
176 def run(self, cmd, timeout=COMMAND_TIMEOUT*2):
177 cmd = "ssh -p %s %s %s@%s '%s'" % (self.port, self.__options_to_str(),
178 self.user, self.host, cmd)
179 #print "SSH.run(%s)" % cmd
180 return CMD.run(self, cmd, timeout)
182 def get_file(self, rmt_filename, local_filename=None):
183 if local_filename == None:
184 local_filename = "./"
185 cmd = "scp -P %s -B %s %s@%s:%s %s" % (self.port, self.__options_to_str(),
186 self.user, self.host,
187 rmt_filename, local_filename)
189 # errors will be on stderr,
190 # success will have a blank stderr...
191 return CMD.run_noexcept(self, cmd)
193 def run_noexcept(self, cmd):
194 cmd = "ssh -p %s %s %s@%s '%s'" % (self.port, self.__options_to_str(),
195 self.user, self.host, cmd)
196 #print "SSH.run_noexcept(%s)" % cmd
197 return CMD.run_noexcept(self, cmd)
199 def run_noexcept2(self, cmd, timeout=COMMAND_TIMEOUT*2):
200 cmd = "exec ssh -p %s %s %s@%s %s" % (self.port, self.__options_to_str(),
201 self.user, self.host, cmd)
202 r = CMD.run_noexcept(self, cmd, timeout)
207 def system2(self, cmd, timeout=COMMAND_TIMEOUT*2):
208 cmd = "ssh -p %s %s %s@%s %s" % (self.port, self.__options_to_str(),
209 self.user, self.host, cmd)
210 #print "SSH.system2(%s)" % cmd
211 return CMD.system(self, cmd, timeout)
214 cmd = "ssh -p %s %s %s@%s '%s'" % (self.port, self.__options_to_str(),
215 self.user, self.host, cmd)
218 (f_in, f_out, f_err) = os.popen3(cmd)
221 if value == "": # An error has occured
223 value = value.strip()
226 print " == %s" % value
235 self.start = time.time()
238 self.end = time.time()
239 t = self.end-self.start
243 self.end = time.time()
244 t = self.end-self.start
245 self.start = self.end