def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False): # NOQA _check_env() if as_root: command = 'echo "{}" | su'.format(escape_double_quotes(command)) device_string = ' -s {}'.format(device) if device else '' full_command = 'adb{} shell "{}"'.format(device_string, escape_double_quotes(command)) logger.debug(full_command) if check_exit_code: actual_command = "adb{} shell '({}); echo $?'".format( device_string, escape_single_quotes(command)) raw_output, error = check_output(actual_command, timeout, shell=True) if raw_output: try: output, exit_code, _ = raw_output.rsplit('\n', 2) except ValueError: exit_code, _ = raw_output.rsplit('\n', 1) output = '' else: # raw_output is empty exit_code = '969696' # just because output = '' exit_code = exit_code.strip() if exit_code.isdigit(): if int(exit_code): message = 'Got exit code {}\nfrom: {}\nSTDOUT: {}\nSTDERR: {}' raise TargetError( message.format(exit_code, full_command, output, error)) elif AM_START_ERROR.findall(output): message = 'Could not start activity; got the following:' message += '\n{}'.format(AM_START_ERROR.findall(output)[0]) raise TargetError(message) else: # not all digits if AM_START_ERROR.findall(output): message = 'Could not start activity; got the following:\n{}' raise TargetError( message.format(AM_START_ERROR.findall(output)[0])) else: message = 'adb has returned early; did not get an exit code. '\ 'Was kill-server invoked?' raise TargetError(message) else: # do not check exit code output, _ = check_output(full_command, timeout, shell=True) return output
def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False): # NOQA _check_env() if as_root: command = 'echo "{}" | su'.format(escape_double_quotes(command)) device_string = ' -s {}'.format(device) if device else '' full_command = 'adb{} shell "{}"'.format(device_string, escape_double_quotes(command)) logger.debug(full_command) if check_exit_code: actual_command = "adb{} shell '({}); echo $?'".format(device_string, escape_single_quotes(command)) raw_output, error = check_output(actual_command, timeout, shell=True) if raw_output: try: output, exit_code, _ = raw_output.rsplit('\n', 2) except ValueError: exit_code, _ = raw_output.rsplit('\n', 1) output = '' else: # raw_output is empty exit_code = '969696' # just because output = '' exit_code = exit_code.strip() if exit_code.isdigit(): if int(exit_code): message = 'Got exit code {}\nfrom: {}\nSTDOUT: {}\nSTDERR: {}' raise TargetError(message.format(exit_code, full_command, output, error)) elif AM_START_ERROR.findall(output): message = 'Could not start activity; got the following:' message += '\n{}'.format(AM_START_ERROR.findall(output)[0]) raise TargetError(message) else: # not all digits if AM_START_ERROR.findall(output): message = 'Could not start activity; got the following:\n{}' raise TargetError(message.format(AM_START_ERROR.findall(output)[0])) else: message = 'adb has returned early; did not get an exit code. '\ 'Was kill-server invoked?' raise TargetError(message) else: # do not check exit code output, _ = check_output(full_command, timeout, shell=True) return output
def adb_background_shell(device, command, stdout=subprocess.PIPE, stderr=subprocess.PIPE, as_root=False): """Runs the sepcified command in a subprocess, returning the the Popen object.""" _check_env() if as_root: command = 'echo \'{}\' | su'.format(escape_single_quotes(command)) device_string = ' -s {}'.format(device) if device else '' full_command = 'adb{} shell "{}"'.format(device_string, escape_double_quotes(command)) logger.debug(full_command) return subprocess.Popen(full_command, stdout=stdout, stderr=stderr, shell=True)
def execute(self, state, args): name = identifier(args.plugin) rst_output = None if name == caseless_string('settings'): rst_output = get_rst_for_global_config() rst_output += get_rst_for_envars() plugin_name = name.lower() kind = 'global:' else: try: plugin = pluginloader.get_plugin_class(name) except NotFoundError: plugin = None if plugin: rst_output = get_rst_from_plugin(plugin) plugin_name = plugin.name kind = '{}:'.format(plugin.kind) else: target = get_target_description(name) if target: rst_output = get_rst_from_target(target) plugin_name = target.name kind = 'target:' if not rst_output: raise NotFoundError( 'Could not find plugin or alias "{}"'.format(name)) if which('pandoc'): p = Popen(['pandoc', '-f', 'rst', '-t', 'man'], stdin=PIPE, stdout=PIPE, stderr=PIPE) if sys.version_info[0] == 3: output, _ = p.communicate(rst_output.encode( sys.stdin.encoding)) output = output.decode(sys.stdout.encoding) else: output, _ = p.communicate(rst_output) # Make sure to double escape back slashes output = output.replace('\\', '\\\\\\') # Correctly format the title and page number of the man page title, body = output.split('\n', 1) title = '.TH {}{} 7'.format(kind, plugin_name) output = '\n'.join([title, body]) call('echo "{}" | man -l -'.format(escape_double_quotes(output)), shell=True) else: print(rst_output) # pylint: disable=superfluous-parens
def execute(self, state, args): name = identifier(args.plugin) rst_output = None if name == caseless_string('settings'): rst_output = get_rst_for_global_config() rst_output += get_rst_for_envars() plugin_name = name.lower() kind = 'global:' else: try: plugin = pluginloader.get_plugin_class(name) except NotFoundError: plugin = None if plugin: rst_output = get_rst_from_plugin(plugin) plugin_name = plugin.name kind = '{}:'.format(plugin.kind) else: target = get_target_description(name) if target: rst_output = get_rst_from_target(target) plugin_name = target.name kind = 'target:' if not rst_output: raise NotFoundError('Could not find plugin or alias "{}"'.format(name)) if which('pandoc'): p = Popen(['pandoc', '-f', 'rst', '-t', 'man'], stdin=PIPE, stdout=PIPE, stderr=PIPE) if sys.version_info[0] == 3: output, _ = p.communicate(rst_output.encode(sys.stdin.encoding)) output = output.decode(sys.stdout.encoding) else: output, _ = p.communicate(rst_output) # Make sure to double escape back slashes output = output.replace('\\', '\\\\\\') # Correctly format the title and page number of the man page title, body = output.split('\n', 1) title = '.TH {}{} 7'.format(kind, plugin_name) output = '\n'.join([title, body]) call('echo "{}" | man -l -'.format(escape_double_quotes(output)), shell=True) else: print(rst_output) # pylint: disable=superfluous-parens
def kick_off(self, command, as_root=False): command = 'sh -c "{}" 1>/dev/null 2>/dev/null &'.format(escape_double_quotes(command)) return self.conn.execute(command, as_root=as_root)
def _gem5_shell(self, command, as_root=False, timeout=None, check_exit_code=True, sync=True): # pylint: disable=R0912 """ Execute a command in the gem5 shell This wraps the telnet connection to gem5 and processes the raw output. This method waits for the shell to return, and then will try and separate the output from the command from the command itself. If this fails, warn, but continue with the potentially wrong output. The exit code is also checked by default, and non-zero exit codes will raise a TargetError. """ if sync: self._sync_gem5_shell() gem5_logger.debug("gem5_shell command: {}".format(command)) if as_root: command = 'echo "{}" | su'.format(escape_double_quotes(command)) # Send the actual command self.conn.send("{}\n".format(command)) # Wait for the response. We just sit here and wait for the prompt to # appear, as gem5 might take a long time to provide the output. This # avoids timeout issues. command_index = -1 while command_index == -1: if self.conn.prompt(): output = re.sub(r' \r([^\n])', r'\1', self.conn.before) output = re.sub(r'[\b]', r'', output) # Deal with line wrapping output = re.sub(r'[\r].+?<', r'', output) command_index = output.find(command) # If we have -1, then we cannot match the command, but the # prompt has returned. Hence, we have a bit of an issue. We # warn, and return the whole output. if command_index == -1: gem5_logger.warn("gem5_shell: Unable to match command in " "command output. Expect parsing errors!") command_index = 0 output = output[command_index + len(command):].strip() # If the gem5 system echoes the executed command, we need to remove that too! if self.strip_echoed_commands: command_index = output.find(command) if command_index != -1: output = output[command_index + len(command):].strip() gem5_logger.debug("gem5_shell output: {}".format(output)) # We get a second prompt. Hence, we need to eat one to make sure that we # stay in sync. If we do not do this, we risk getting out of sync for # slower simulations. self.conn.expect([self.conn.UNIQUE_PROMPT, self.conn.PROMPT], timeout=self.default_timeout) if check_exit_code: exit_code_text = self._gem5_shell('echo $?', as_root=as_root, timeout=timeout, check_exit_code=False, sync=False) try: exit_code = int(exit_code_text.split()[0]) if exit_code: message = 'Got exit code {}\nfrom: {}\nOUTPUT: {}' raise TargetError(message.format(exit_code, command, output)) except (ValueError, IndexError): gem5_logger.warning('Could not get exit code for "{}",\ngot: "{}"'.format(command, exit_code_text)) return output
def pull(self, source, dest, timeout=30): source = '"{}"@"{}":"{}"'.format(escape_double_quotes(self.username), escape_spaces(escape_double_quotes(self.host)), escape_spaces(escape_double_quotes(source))) return self._scp(source, dest, timeout)
def _gem5_shell(self, command, as_root=False, timeout=None, check_exit_code=True, sync=True): # pylint: disable=R0912 """ Execute a command in the gem5 shell This wraps the telnet connection to gem5 and processes the raw output. This method waits for the shell to return, and then will try and separate the output from the command from the command itself. If this fails, warn, but continue with the potentially wrong output. The exit code is also checked by default, and non-zero exit codes will raise a TargetError. """ if sync: self._sync_gem5_shell() gem5_logger.debug("gem5_shell command: {}".format(command)) if as_root: command = 'echo "{}" | su'.format(escape_double_quotes(command)) # Send the actual command self.conn.send("{}\n".format(command)) # Wait for the response. We just sit here and wait for the prompt to # appear, as gem5 might take a long time to provide the output. This # avoids timeout issues. command_index = -1 while command_index == -1: if self.conn.prompt(): output = re.sub(r' \r([^\n])', r'\1', self.conn.before) output = re.sub(r'[\b]', r'', output) # Deal with line wrapping output = re.sub(r'[\r].+?<', r'', output) command_index = output.find(command) # If we have -1, then we cannot match the command, but the # prompt has returned. Hence, we have a bit of an issue. We # warn, and return the whole output. if command_index == -1: gem5_logger.warn("gem5_shell: Unable to match command in " "command output. Expect parsing errors!") command_index = 0 output = output[command_index + len(command):].strip() # It is possible that gem5 will echo the command. Therefore, we need to # remove that too! command_index = output.find(command) if command_index != -1: output = output[command_index + len(command):].strip() gem5_logger.debug("gem5_shell output: {}".format(output)) # We get a second prompt. Hence, we need to eat one to make sure that we # stay in sync. If we do not do this, we risk getting out of sync for # slower simulations. self.conn.expect([self.conn.UNIQUE_PROMPT, self.conn.PROMPT], timeout=self.default_timeout) if check_exit_code: exit_code_text = self._gem5_shell('echo $?', as_root=as_root, timeout=timeout, check_exit_code=False, sync=False) try: exit_code = int(exit_code_text.split()[0]) if exit_code: message = 'Got exit code {}\nfrom: {}\nOUTPUT: {}' raise TargetError(message.format(exit_code, command, output)) except (ValueError, IndexError): gem5_logger.warning('Could not get exit code for "{}",\ngot: "{}"'.format(command, exit_code_text)) return output