6 class ExceptionTimeout(Exception): pass
7 class ExceptionReadTimeout(Exception): pass
9 ssh_options = { 'StrictHostKeyChecking':'no',
11 'PasswordAuthentication':'no',
12 'ConnectTimeout':'%s' % COMMAND_TIMEOUT}
13 from select import select
17 class Sopen(subprocess.Popen):
18 def kill(self, sig = signal.SIGTERM):
20 # NOTE: this also kills parent... so doesn't work like I want.
21 # NOTE: adding 'exec' before the cmd removes the extra sh, and
22 # partially addresses this problem.
23 #os.killpg(os.getpgid(self.pid), signal.SIGKILL)
24 os.kill(self.pid, sig)
26 # no such process, due to it already exiting...
30 def read_t(stream, count=1, timeout=COMMAND_TIMEOUT*2):
35 lin, lout, lerr = select([stream], [], [], timeout)
38 raise ExceptionReadTimeout("TIMEOUT reading from command")
41 outbytes = stream.read(count)
43 print 'no content yet.'
45 # the select timeout should catch this.
54 lin, lout, lerr = select([stream], [], [], timeout)
56 raise ExceptionReadTimeout("TIMEOUT reading from command")
58 return stream.read(count)
64 def run_noexcept(self, cmd, timeout=COMMAND_TIMEOUT*2):
67 return CMD.run(self,cmd,timeout)
68 except ExceptionTimeout:
69 import traceback; print traceback.print_exc()
70 return ("", "ScriptTimeout")
71 except ExceptionReadTimeout:
72 print traceback.print_exc()
73 return ("", "RunningScriptTimeout")
74 except Exception, err:
75 from nodecommon import email_exception
79 def system(self, cmd, timeout=COMMAND_TIMEOUT*2):
80 (o,e) = self.run(cmd, timeout)
83 if self.s.returncode is None:
85 return self.s.returncode
87 def run(self, cmd, timeout=COMMAND_TIMEOUT*2):
89 print "CMD.run(%s)" % cmd
90 s = Sopen(cmd, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
92 (f_in, f_out, f_err) = (s.stdin, s.stdout, s.stderr)
93 lout, lin, lerr = select([f_out], [], [f_err], timeout)
94 if len(lin) == 0 and len(lout) == 0 and len(lerr) == 0:
95 # Reached a timeout! Nuke process so it does not hang.
96 print "TIMEOUT!!!!!!!!!!!!!!!!!!!"
97 s.kill(signal.SIGKILL)
98 raise ExceptionTimeout("TIMEOUT Running: %s" % cmd)
101 #print len(lin), len(lout), len(lerr)
107 #print "reading from f_out"
108 #if len(lout) > 0: o_value = f_out.read()
109 #print "reading from f_err"
110 #if len(lerr) > 0: e_value = f_err.read()
111 #o_value = f_out.read()
112 flags = fcntl.fcntl(f_out, fcntl.F_GETFL)
113 fcntl.fcntl(f_out, fcntl.F_SETFL, flags | os.O_NONBLOCK)
116 o_value = read_t(f_out,1,30)
117 except ExceptionReadTimeout:
118 s.kill(signal.SIGKILL)
119 raise ExceptionReadTimeout("TIMEOUT: failed to read from cmd: %s" % cmd)
121 e_value = f_err.read()
123 o_value = o_value.strip()
124 e_value = e_value.strip()
129 s.kill(signal.SIGKILL)
131 return (o_value, e_value)
133 def runargs(self, args, timeout=COMMAND_TIMEOUT*2):
135 #print "CMD.run(%s)" % " ".join(args)
136 s = Sopen(args, shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
138 (f_in, f_out, f_err) = (s.stdin, s.stdout, s.stderr)
139 lout, lin, lerr = select([f_out], [], [f_err], timeout)
140 if len(lin) == 0 and len(lout) == 0 and len(lerr) == 0:
141 # Reached a timeout! Nuke process so it does not hang.
142 s.kill(signal.SIGKILL)
143 raise ExceptionTimeout("TIMEOUT Running: %s" % cmd)
144 o_value = f_out.read()
146 if o_value == "": # An error has occured
147 e_value = f_err.read()
149 o_value = o_value.strip()
150 e_value = e_value.strip()
155 s.kill(signal.SIGKILL)
157 return (o_value, e_value)
161 def __init__(self, user, host, port=22, options = ssh_options):
162 self.options = options
168 def __options_to_str(self):
170 for o,v in self.options.iteritems():
171 options = options + "-o %s=%s " % (o,v)
174 def run(self, cmd, timeout=COMMAND_TIMEOUT*2):
175 cmd = "ssh -p %s %s %s@%s '%s'" % (self.port, self.__options_to_str(),
176 self.user, self.host, cmd)
177 #print "SSH.run(%s)" % cmd
178 return CMD.run(self, cmd, timeout)
180 def get_file(self, rmt_filename, local_filename=None):
181 if local_filename == None:
182 local_filename = "./"
183 cmd = "scp -P %s -B %s %s@%s:%s %s" % (self.port, self.__options_to_str(),
184 self.user, self.host,
185 rmt_filename, local_filename)
187 # errors will be on stderr,
188 # success will have a blank stderr...
189 return CMD.run_noexcept(self, cmd)
191 def run_noexcept(self, cmd):
192 cmd = "ssh -p %s %s %s@%s '%s'" % (self.port, self.__options_to_str(),
193 self.user, self.host, cmd)
194 #print "SSH.run_noexcept(%s)" % cmd
195 return CMD.run_noexcept(self, cmd)
197 def run_noexcept2(self, cmd, timeout=COMMAND_TIMEOUT*2):
198 cmd = "exec ssh -p %s %s %s@%s %s" % (self.port, self.__options_to_str(),
199 self.user, self.host, cmd)
200 r = CMD.run_noexcept(self, cmd, timeout)
205 def system2(self, cmd, timeout=COMMAND_TIMEOUT*2):
206 cmd = "ssh -p %s %s %s@%s %s" % (self.port, self.__options_to_str(),
207 self.user, self.host, cmd)
208 #print "SSH.system2(%s)" % cmd
209 return CMD.system(self, cmd, timeout)
212 cmd = "ssh -p %s %s %s@%s '%s'" % (self.port, self.__options_to_str(),
213 self.user, self.host, cmd)
216 (f_in, f_out, f_err) = os.popen3(cmd)
219 if value == "": # An error has occured
221 value = value.strip()
224 print " == %s" % value
233 self.start = time.time()
236 self.end = time.time()
237 t = self.end-self.start
241 self.end = time.time()
242 t = self.end-self.start
243 self.start = self.end