Esempio n. 1
0
 def sh(self, args, stdin=b'', shell=False, env=None, check=True,
        watcher=None, short_args=None, stdout=None, stderr=None):
     """run a shell command"""
     start = time.time()
     env_ = os.environ.copy()
     env_.update(LC_ALL='C', LANG='C')
     if env:
         env_.update(env)
     kwargs = dict(self.stds, shell=shell)
     if stdout is not None:
         kwargs['stdout'] = stdout
     if stderr is not None:
         kwargs['stderr'] = stderr
     res = {'stdout': '', 'stderr': ''}
     try:
         p = subprocess.Popen(args, env=env_, **kwargs)
     except Exception:
         rc = res['rc'] = 1
         exc = self.format_exception()
     else:
         self.current_cmd = short_args or args
         self.current_process = p
         if watcher is not None:
             self.current_process_watcher = safe_iterator(watcher(self, p))
         else:
             self.current_process_watcher = safe_iterator()
         if stdin and not isinstance(stdin, bytes):
             stdin = stdin.encode('utf8')
         stdout, stderr = p.communicate(stdin)
         self.current_process = None
         utils._next(self.current_process_watcher)
         self.current_process_watcher = None
         if stdout is None:
             stdout = kwargs['stdout']
             with open(stdout.name) as fd:
                 try:
                     stdout = fd.read()
                 except OSError:
                     stdout = ''
         if isinstance(stdout, bytes):
             stdout = stdout.decode('utf8')
         if stderr is None:
             stderr = kwargs['stderr']
             with open(stderr.name) as fd:
                 try:
                     stderr = fd.read()
                 except OSError:
                     stderr = ''
         if isinstance(stderr, bytes):
             stderr = stderr.decode('utf8')
         rc = p.returncode
         res.update(rc=rc, stdout=stdout, stderr=stderr)
         exc = None
     t = time.time() - start
     self.remote_calls.append(dict(res, cmd=args, start=start, time=t,
                                   exc=exc))
     if check:
         return self.check(res)
     return res
Esempio n. 2
0
def safe_iterator(iterator=None):
    while True:
        if iterator is not None:
            try:
                utils._next(iterator)
            except Exception:
                logging.exception(iterator)
        yield
Esempio n. 3
0
 def on_alarm(self, *args):
     self.alarm_count += 1
     ready = select.select([sys.stdin], [], [], .0)[0]
     if ready:
         try:
             data = utils.proto_loads_std(self.stdin)
         except ValueError:
             pass
         else:
             sig = data.get('signal')
             if sig is not None:
                 self.on_sigint()
     if self.alarm_count % self.process_watcher_delay == 0:
         if self.current_process_watcher is not None:
             utils._next(self.current_process_watcher)
     signal.alarm(self.alarm_delay)
Esempio n. 4
0
 def on_sigint(self, *args):
     res = dict(rc=1, signal='SIGINT', current_process=None)
     if self.current_process is not None:
         # forward signal to current process if any
         p = self.current_process
         p.send_signal(signal.SIGINT)
         # let the watcher know that we no longer have a process
         if self.current_process_watcher is not None:
             self.current_process = None
             utils._next(self.current_process_watcher)
         p.wait()
         res['current_process'] = {
             'cmd': self.current_cmd,
             'pid': p.pid,
             'rc': p.returncode}
     # clean exit
     self.exit(res)
Esempio n. 5
0
 def exit(self, res):
     # tel the watcher that the process is ended
     if self.current_process_watcher is not None:
         self.current_process = None
         utils._next(self.current_process_watcher)
     res.setdefault('rc', 0)
     res.setdefault('message_type', 'exit')
     res.setdefault('signal', None)
     res['meta'] = dict(remote_calls=self.remote_calls,
                        remote_time=time.time() - self.remote_start)
     self.logfile.seek(0)
     logs = self.logfile.read()
     if logs.strip():
         res['log'] = logs
     if 'diff' in res:
         res.setdefault('changed', bool(res['diff']))
     utils.proto_dumps_std_threadsafe(res, sys.stdout)
     sys.exit(0)