def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False, newline_separator='\r\n'): # NOQA _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) if check_exit_code: actual_command = "adb{} shell '({}); echo \"\n$?\"'".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(newline_separator, 2) except ValueError: exit_code, _ = raw_output.rsplit(newline_separator, 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 _execute_and_wait_for_prompt(self, command, timeout=None, as_root=False, strip_colors=True, log=True): self.conn.prompt(0.1) # clear an existing prompt if there is one. if as_root: command = "sudo -- sh -c '{}'".format(escape_single_quotes(command)) if log: logger.debug(command) self.conn.sendline(command) if self.password: index = self.conn.expect_exact([self.password_prompt, TIMEOUT], timeout=0.5) if index == 0: self.conn.sendline(self.password) else: # not as_root if log: logger.debug(command) self.conn.sendline(command) timed_out = self._wait_for_prompt(timeout) # the regex removes line breaks potential introduced when writing # command to shell. output = process_backspaces(self.conn.before) output = re.sub(r"\r([^\n])", r"\1", output) if "\r\n" in output: # strip the echoed command output = output.split("\r\n", 1)[1] if timed_out: self.cancel_running_command() raise TimeoutError(command, output) if strip_colors: output = strip_bash_colors(output) return output
def _execute_and_wait_for_prompt(self, command, timeout=None, as_root=False, strip_colors=True, log=True): self.conn.prompt(0.1) # clear an existing prompt if there is one. if as_root: command = "sudo -- sh -c '{}'".format( escape_single_quotes(command)) if log: logger.debug(command) self.conn.sendline(command) if self.password: index = self.conn.expect_exact([self.password_prompt, TIMEOUT], timeout=0.5) if index == 0: self.conn.sendline(self.password) else: # not as_root if log: logger.debug(command) self.conn.sendline(command) timed_out = self._wait_for_prompt(timeout) # the regex removes line breaks potential introduced when writing # command to shell. output = process_backspaces(self.conn.before) output = re.sub(r'\r([^\n])', r'\1', output) if '\r\n' in output: # strip the echoed command output = output.split('\r\n', 1)[1] if timed_out: self.cancel_running_command() raise TimeoutError(command, output) if strip_colors: output = strip_bash_colors(output) return output
def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False, adb_server=None): # NOQA _check_env() if as_root: command = 'echo \'{}\' | su'.format(escape_single_quotes(command)) device_part = [] if adb_server: device_part = ['-H', adb_server] device_part += ['-s', device] if device else [] # On older combinations of ADB/Android versions, the adb host command always # exits with 0 if it was able to run the command on the target, even if the # command failed (https://code.google.com/p/android/issues/detail?id=3254). # Homogenise this behaviour by running the command then echoing the exit # code. adb_shell_command = '({}); echo \"\n$?\"'.format(command) actual_command = ['adb'] + device_part + ['shell', adb_shell_command] logger.debug('adb {} shell {}'.format(' '.join(device_part), command)) raw_output, error = check_output(actual_command, timeout, shell=False) if raw_output: try: output, exit_code, _ = raw_output.replace('\r\n', '\n').replace( '\r', '\n').rsplit('\n', 2) except ValueError: exit_code, _ = raw_output.replace('\r\n', '\n').replace( '\r', '\n').rsplit('\n', 1) output = '' else: # raw_output is empty exit_code = '969696' # just because output = '' if check_exit_code: exit_code = exit_code.strip() re_search = AM_START_ERROR.findall('{}\n{}'.format(output, error)) if exit_code.isdigit(): if int(exit_code): message = ('Got exit code {}\nfrom target command: {}\n' 'STDOUT: {}\nSTDERR: {}') raise TargetError( message.format(exit_code, command, output, error)) elif re_search: message = 'Could not start activity; got the following:\n{}' raise TargetError(message.format(re_search[0])) else: # not all digits if re_search: message = 'Could not start activity; got the following:\n{}' raise TargetError(message.format(re_search[0])) else: message = 'adb has returned early; did not get an exit code. '\ 'Was kill-server invoked?\nOUTPUT:\n-----\n{}\n'\ '-----\nERROR:\n-----\n{}\n-----' raise TargetError(message.format(raw_output, error)) return output
def adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False, newline_separator='\r\n'): # NOQA _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) if check_exit_code: actual_command = "adb{} shell '({}); echo \"\n$?\"'".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(newline_separator, 2) except ValueError: exit_code, _ = raw_output.rsplit(newline_separator, 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 adb_shell(device, command, timeout=None, check_exit_code=False, as_root=False, adb_server=None): # NOQA _check_env() if as_root: command = 'echo \'{}\' | su'.format(escape_single_quotes(command)) device_part = [] if adb_server: device_part = ['-H', adb_server] device_part += ['-s', device] if device else [] # On older combinations of ADB/Android versions, the adb host command always # exits with 0 if it was able to run the command on the target, even if the # command failed (https://code.google.com/p/android/issues/detail?id=3254). # Homogenise this behaviour by running the command then echoing the exit # code. adb_shell_command = '({}); echo \"\n$?\"'.format(command) actual_command = ['adb'] + device_part + ['shell', adb_shell_command] logger.debug('adb {} shell {}'.format(' '.join(device_part), command)) raw_output, error = check_output(actual_command, timeout, shell=False) if raw_output: try: output, exit_code, _ = raw_output.replace('\r\n', '\n').replace('\r', '\n').rsplit('\n', 2) except ValueError: exit_code, _ = raw_output.replace('\r\n', '\n').replace('\r', '\n').rsplit('\n', 1) output = '' else: # raw_output is empty exit_code = '969696' # just because output = '' if check_exit_code: exit_code = exit_code.strip() re_search = AM_START_ERROR.findall('{}\n{}'.format(output, error)) if exit_code.isdigit(): if int(exit_code): message = ('Got exit code {}\nfrom target command: {}\n' 'STDOUT: {}\nSTDERR: {}') raise TargetError(message.format(exit_code, command, output, error)) elif re_search: message = 'Could not start activity; got the following:\n{}' raise TargetError(message.format(re_search[0])) else: # not all digits if re_search: message = 'Could not start activity; got the following:\n{}' raise TargetError(message.format(re_search[0])) else: message = 'adb has returned early; did not get an exit code. '\ 'Was kill-server invoked?\nOUTPUT:\n-----\n{}\n'\ '-----\nERROR:\n-----\n{}\n-----' raise TargetError(message.format(raw_output, error)) return output
def _execute_and_wait_for_prompt(self, command, timeout=None, as_root=False, strip_colors=True, log=True): self.conn.prompt(0.1) # clear an existing prompt if there is one. if self.username == 'root': # As we're already root, there is no need to use sudo. as_root = False if as_root: command = self.sudo_cmd.format(escape_single_quotes(command)) if log: logger.debug(command) self.conn.sendline(command) if self.password: index = self.conn.expect_exact([self.password_prompt, TIMEOUT], timeout=0.5) if index == 0: self.conn.sendline(self.password) else: # not as_root if log: logger.debug(command) self.conn.sendline(command) timed_out = self._wait_for_prompt(timeout) # the regex removes line breaks potential introduced when writing # command to shell. if sys.version_info[0] == 3: output = process_backspaces( self.conn.before.decode(sys.stdout.encoding, 'replace')) else: output = process_backspaces(self.conn.before) output = re.sub(r'\r([^\n])', r'\1', output) if '\r\n' in output: # strip the echoed command output = output.split('\r\n', 1)[1] if timed_out: self.cancel_running_command() raise TimeoutError(command, output) if strip_colors: output = strip_bash_colors(output) return output