def __init__(self, arguments, name=None, env=-1, cwd=None, output_to_shell=False, use_logfiles=True): command_safe = False if type(arguments) in (list, tuple): self.command = escape_arguments_to_string(arguments) command_safe = True else: self.command = arguments[:] self.start_time = time.localtime() kwargs = {} if env == -1: kwargs['env'] = common.copy(common.ENV) else: kwargs['env'] = env if cwd is not None: kwargs['cwd'] = cwd if output_to_shell: kwargs['stdin'] = sys.stdin kwargs['stdout'] = sys.stdout kwargs['stderr'] = sys.stderr elif use_logfiles: # If we are not outputting to the shell # the output will be routed to two files in /tmp. conf_name = util.string_safe_chars( env.get('WINEPREFIXNAME', common.ENV.get('WINEPREFIXNAME', '')) ) self.log_filename_base = '%s-%s-%s' % ( conf_name, time.strftime('%Y-%m-%d-%H:%M:%S', self.start_time), util.string_random() ) self.log_filename_out = '{tmppath}/run-process-{filename}.out'.format( tmppath = common.ENV['VINEYARDTMP'], filename = self.log_filename_base) self.log_filename_err = '{tmppath}/run-process-{filename}.err'.format( tmppath = common.ENV['VINEYARDTMP'], filename = self.log_filename_base) self.log_out_last_pos = 0 self.log_err_last_pos = 0 if command_safe: self.command = "%s 2>%s 1>%s" % ( self.command, self.log_filename_err, self.log_filename_out ) else: self.command = "%s 2>%s 1>%s" % ( util.string_safe_shell(self.command), self.log_filename_err, self.log_filename_out ) # Use a new process group for this process if 'preexec_fn' not in kwargs: kwargs['preexec_fn'] = os.setpgrp if 'env' in kwargs: self.shell = common.which(['dash', 'bash', 'sh'], kwargs['env']) else: self.shell = common.which(['dash', 'bash', 'sh']) print("Going to run:", self.shell, '-c', '--', 'exec %s' % self.command) self.child = Popen([ self.shell, '-c', '--', 'exec %s' % self.command ], **kwargs) print("Running:", self.shell, '-c', '--', 'exec %s' % self.command) self._kwargs = kwargs self.pid = self.child.pid self.returncode = self.child.returncode self.send_signal = self.child.send_signal self.terminate = self.child.terminate self.kill = self.child.kill
class run: log_filename_out = None log_filename_err = None def __init__(self, arguments, name=None, env=-1, cwd=None, output_to_shell=False, use_logfiles=True): command_safe = False if type(arguments) in (list, tuple): self.command = escape_arguments_to_string(arguments) command_safe = True else: self.command = arguments[:] self.start_time = time.localtime() kwargs = {} if env == -1: kwargs['env'] = common.copy(common.ENV) else: kwargs['env'] = env if cwd is not None: kwargs['cwd'] = cwd if output_to_shell: kwargs['stdin'] = sys.stdin kwargs['stdout'] = sys.stdout kwargs['stderr'] = sys.stderr elif use_logfiles: # If we are not outputting to the shell # the output will be routed to two files in /tmp. conf_name = util.string_safe_chars( env.get('WINEPREFIXNAME', common.ENV.get('WINEPREFIXNAME', '')) ) self.log_filename_base = '%s-%s-%s' % ( conf_name, time.strftime('%Y-%m-%d-%H:%M:%S', self.start_time), util.string_random() ) self.log_filename_out = '{tmppath}/run-process-{filename}.out'.format( tmppath = common.ENV['VINEYARDTMP'], filename = self.log_filename_base) self.log_filename_err = '{tmppath}/run-process-{filename}.err'.format( tmppath = common.ENV['VINEYARDTMP'], filename = self.log_filename_base) self.log_out_last_pos = 0 self.log_err_last_pos = 0 if command_safe: self.command = "%s 2>%s 1>%s" % ( self.command, self.log_filename_err, self.log_filename_out ) else: self.command = "%s 2>%s 1>%s" % ( util.string_safe_shell(self.command), self.log_filename_err, self.log_filename_out ) # Use a new process group for this process if 'preexec_fn' not in kwargs: kwargs['preexec_fn'] = os.setpgrp if 'env' in kwargs: self.shell = common.which(['dash', 'bash', 'sh'], kwargs['env']) else: self.shell = common.which(['dash', 'bash', 'sh']) print("Going to run:", self.shell, '-c', '--', 'exec %s' % self.command) self.child = Popen([ self.shell, '-c', '--', 'exec %s' % self.command ], **kwargs) print("Running:", self.shell, '-c', '--', 'exec %s' % self.command) self._kwargs = kwargs self.pid = self.child.pid self.returncode = self.child.returncode self.send_signal = self.child.send_signal self.terminate = self.child.terminate self.kill = self.child.kill def communicate(self): """ Wait for the child process to finish, then return the stdout and stderr of it as a tuple in the form of (stdout, stderr).""" if self.child.returncode != None: # Process has finished return None if self.log_filename_out == None: return self.child.communicate() else: self.child.communicate() return self.read(with_stdout=True, with_stderr=True, since_last=True) def read(self, size=-1, with_stdout = True, with_stderr = True, since_last=False): """ Read the stdout and/or stderr of the child process. If since_last is true only the output given since the last read is returned. If since_last is false the entire output stream is returned.""" return _read(self, size=size, with_stdout=with_stdout, with_stderr=with_stderr, since_last=since_last) def read_stdout(self, since_last=False): return self.read(with_stdout = True, with_stderr = False, since_last = since_last) def read_stderr(self, since_last=False): return self.read(with_stderr = True, with_stdout = False, since_last = since_last) def poll(self): """ Check if child process has terminated. Set and return returncode attribute.""" # poll() has already been run, return the already given returncode if self.returncode != None: return self.returncode self.returncode = self.child.poll() # If process has terminated, delete it's object so the process can be freed if self.returncode != None: del self.child self.child = None return self.returncode