def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): cmdline = self._escapedCommandLine(cmd) if env: cmdline = '%s %s' % (self._formatEnvString(env), cmdline) # execcwd/execcwdsu currently unsupported in Negatus; see bug 824127. if cwd and self.agentProductName == 'SUTAgentNegatus': raise DMError("Negatus does not support execcwd/execcwdsu") haveExecSu = ( self.agentProductName == 'SUTAgentNegatus' or StrictVersion(self.agentVersion) >= StrictVersion('1.13')) # Depending on agent version we send one of the following commands here: # * exec (run as normal user) # * execsu (run as privileged user) # * execcwd (run as normal user from specified directory) # * execcwdsu (run as privileged user from specified directory) cmd = "exec" if cwd: cmd += "cwd" if root and haveExecSu: cmd += "su" if cwd: self._sendCmds([{ 'cmd': '%s %s %s' % (cmd, cwd, cmdline) }], outputfile, timeout) else: if (not root) or haveExecSu: self._sendCmds([{ 'cmd': '%s %s' % (cmd, cmdline) }], outputfile, timeout) else: # need to manually inject su -c for backwards compatibility (this may # not work on ICS or above!!) # (FIXME: this backwards compatibility code is really ugly and should # be deprecated at some point in the future) self._sendCmds([{ 'cmd': '%s su -c "%s"' % (cmd, cmdline) }], outputfile, timeout) # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value raise DMError( "Automation Error: Error finding end of line/return value when running '%s'" % cmdline)
def shell(self, cmd, outputfile, env=None, cwd=None): cmdline = self._escapedCommandLine(cmd) if env: cmdline = '%s %s' % (self.formatEnvString(env), cmdline) try: if cwd: self.sendCmds([{ 'cmd': 'execcwd %s %s' % (cwd, cmdline) }], outputfile) else: self.sendCmds([{ 'cmd': 'exec su -c "%s"' % cmdline }], outputfile) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): """ Executes shell command on device. cmd - Command string to execute outputfile - File to store output env - Environment to pass to exec command cwd - Directory to execute command from timeout - specified in seconds, defaults to 'default_timeout' root - Specifies whether command requires root privileges returns: success: Return code from command failure: None """ cmdline = self._escapedCommandLine(cmd) if env: cmdline = '%s %s' % (self._formatEnvString(env), cmdline) haveExecSu = (StrictVersion(self.agentVersion) >= StrictVersion('1.13')) # Depending on agent version we send one of the following commands here: # * exec (run as normal user) # * execsu (run as privileged user) # * execcwd (run as normal user from specified directory) # * execcwdsu (run as privileged user from specified directory) cmd = "exec" if cwd: cmd += "cwd" if root and haveExecSu: cmd += "su" try: if cwd: self._sendCmds([{ 'cmd': '%s %s %s' % (cmd, cwd, cmdline) }], outputfile, timeout) else: if (not root) or haveExecSu: self._sendCmds([{ 'cmd': '%s %s' % (cmd, cmdline) }], outputfile, timeout) else: # need to manually inject su -c for backwards compatibility (this may # not work on ICS or above!!) # (FIXME: this backwards compatibility code is really ugly and should # be deprecated at some point in the future) self._sendCmds([ { 'cmd': '%s su -c "%s"' % (cmd, cmdline) }], outputfile, timeout) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): # FIXME: this function buffers all output of the command into memory, # always. :( # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it if root: cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd) else: cmdline = self._escapedCommandLine(cmd) cmdline += "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join( map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args = [self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if timeout: timeout = int(timeout) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: time.sleep(1) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for shell call") (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): """ Executes shell command on device. Returns exit code. cmd - Command string to execute outputfile - File to store output env - Environment to pass to exec command cwd - Directory to execute command from timeout - specified in seconds, defaults to 'default_timeout' root - Specifies whether command requires root privileges """ cmdline = self._escapedCommandLine(cmd) if env: cmdline = "%s %s" % (self._formatEnvString(env), cmdline) # execcwd/execcwdsu currently unsupported in Negatus; see bug 824127. if cwd and self.agentProductName == "SUTAgentNegatus": raise DMError("Negatus does not support execcwd/execcwdsu") haveExecSu = self.agentProductName == "SUTAgentNegatus" or StrictVersion(self.agentVersion) >= StrictVersion( "1.13" ) # Depending on agent version we send one of the following commands here: # * exec (run as normal user) # * execsu (run as privileged user) # * execcwd (run as normal user from specified directory) # * execcwdsu (run as privileged user from specified directory) cmd = "exec" if cwd: cmd += "cwd" if root and haveExecSu: cmd += "su" if cwd: self._sendCmds([{"cmd": "%s %s %s" % (cmd, cwd, cmdline)}], outputfile, timeout) else: if (not root) or haveExecSu: self._sendCmds([{"cmd": "%s %s" % (cmd, cmdline)}], outputfile, timeout) else: # need to manually inject su -c for backwards compatibility (this may # not work on ICS or above!!) # (FIXME: this backwards compatibility code is really ugly and should # be deprecated at some point in the future) self._sendCmds([{"cmd": '%s su -c "%s"' % (cmd, cmdline)}], outputfile, timeout) # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search("return code \[([0-9]+)\]", lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value raise DMError("Automation Error: Error finding end of line/return value when running '%s'" % cmdline)
def shell(self, cmd, outputfile=None, env=None, cwd=None, timeout=None, root=False): # FIXME: this function buffers all output of the command into memory, # always. :( if outputfile is None: outputfile = StringIO.StringIO() # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it if root: cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd) else: cmdline = self._escapedCommandLine(cmd) cmdline += "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args=[self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if timeout: timeout = int(timeout) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: time.sleep(1) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for shell call") (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): if outputfile is None: outputfile = StringIO.StringIO() cmdline = self._escapedCommandLine(cmd) if env: cmdline = '%s %s' % (self._formatEnvString(env), cmdline) # execcwd/execcwdsu currently unsupported in Negatus; see bug 824127. if cwd and self.agentProductName == 'SUTAgentNegatus': raise DMError("Negatus does not support execcwd/execcwdsu") haveExecSu = (self.agentProductName == 'SUTAgentNegatus' or StrictVersion(self.agentVersion) >= StrictVersion('1.13')) # Depending on agent version we send one of the following commands here: # * exec (run as normal user) # * execsu (run as privileged user) # * execcwd (run as normal user from specified directory) # * execcwdsu (run as privileged user from specified directory) cmd = "exec" if cwd: cmd += "cwd" if root and haveExecSu: cmd += "su" if cwd: self._sendCmds([{ 'cmd': '%s %s %s' % (cmd, cwd, cmdline) }], outputfile, timeout) else: if (not root) or haveExecSu: self._sendCmds([{ 'cmd': '%s %s' % (cmd, cmdline) }], outputfile, timeout) else: # need to manually inject su -c for backwards compatibility (this may # not work on ICS or above!!) # (FIXME: this backwards compatibility code is really ugly and should # be deprecated at some point in the future) self._sendCmds([ { 'cmd': '%s su -c "%s"' % (cmd, cmdline) }], outputfile, timeout) # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value raise DMError("Automation Error: Error finding end of line/return value when running '%s'" % cmdline)
def shell(self, cmd, outputfile, env=None, cwd=None): # need to quote and escape special characters here for (index, arg) in enumerate(cmd): arg.replace('&', '\&') needsQuoting = False for char in [' ', '(', ')', '"', '&']: if arg.find(char): needsQuoting = True break if needsQuoting: cmd[index] = '\'%s\'' % arg # This is more complex than you'd think because adb doesn't actually # return the return code from a process, so we have to capture the output # to get it # FIXME: this function buffers all output of the command into memory, # always. :( cmdline = " ".join(cmd) + "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join( map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args = [self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None): # need to quote and escape special characters here for (index, arg) in enumerate(cmd): arg.replace('&', '\&') needsQuoting = False for char in [ ' ', '(', ')', '"', '&' ]: if arg.find(char): needsQuoting = True break if needsQuoting: cmd[index] = '\'%s\'' % arg # This is more complex than you'd think because adb doesn't actually # return the return code from a process, so we have to capture the output # to get it # FIXME: this function buffers all output of the command into memory, # always. :( cmdline = " ".join(cmd) + "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args=[self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return return_code return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): if outputfile is None: outputfile = StringIO.StringIO() cmdline = self._escapedCommandLine(cmd) if env: cmdline = "%s %s" % (self.formatEnvString(env), cmdline) haveExecSu = StrictVersion(self.agentVersion) >= StrictVersion("1.13") # Depending on agent version we send one of the following commands here: # * exec (run as normal user) # * execsu (run as privileged user) # * execcwd (run as normal user from specified directory) # * execcwdsu (run as privileged user from specified directory) cmd = "exec" if cwd: cmd += "cwd" if root and haveExecSu: cmd += "su" try: if cwd: self.sendCmds([{"cmd": "%s %s %s" % (cmd, cwd, cmdline)}], outputfile, timeout) else: if (not root) or haveExecSu: self.sendCmds([{"cmd": "%s %s" % (cmd, cmdline)}], outputfile, timeout) else: # need to manually inject su -c for backwards compatibility (this may # not work on ICS or above!!) # (FIXME: this backwards compatibility code is really ugly and should # be deprecated at some point in the future) self.sendCmds([{"cmd": '%s su -c "%s"' % (cmd, cmdline)}], outputfile, timeout) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search("return code \[([0-9]+)\]", lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None): # need to quote special characters here for (index, arg) in enumerate(cmd): if arg.find(" ") or arg.find("(") or arg.find(")") or arg.find( "\""): cmd[index] = '\'%s\'' % arg # This is more complex than you'd think because adb doesn't actually # return the return code from a process, so we have to capture the output # to get it # FIXME: this function buffers all output of the command into memory, # always. :( cmdline = " ".join(cmd) + "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join( map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout proc = subprocess.Popen(["adb", "shell", cmdline], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return return_code return None
def shell(self, cmd, outputfile, env=None, cwd=None): cmdline = subprocess.list2cmdline(cmd) if env: cmdline = '%s %s' % (self.formatEnvString(env), cmdline) try: if cwd: self.sendCmds(['execcwd %s %s' % (cwd, cmdline)], outputfile) else: self.sendCmds(['exec su -c "%s"' % cmdline], outputfile) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None): cmdline = subprocess.list2cmdline(cmd) if env: cmdline = '%s %s' % (self.formatEnvString(env), cmdline) try: if cwd: self.sendCmds(['execcwd %s %s' % (cwd, cmdline)], outputfile) else: self.sendCmds(['exec %s' % cmdline], outputfile) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return m.group(1) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None): cmdline = self._escapedCommandLine(cmd) if env: cmdline = "%s %s" % (self.formatEnvString(env), cmdline) try: if cwd: self.sendCmds([{"cmd": "execcwd %s %s" % (cwd, cmdline)}], outputfile, timeout) else: self.sendCmds([{"cmd": 'exec su -c "%s"' % cmdline}], outputfile, timeout) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search("return code \[([0-9]+)\]", lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None): # FIXME: this function buffers all output of the command into memory, # always. :( # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it cmdline = "%s; echo $?" % self._escapedCommandLine(cmd) # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join( map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args = [self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None): # need to quote special characters here for (index, arg) in enumerate(cmd): if arg.find(" ") or arg.find("(") or arg.find(")") or arg.find("\""): cmd[index] = '\'%s\'' % arg # This is more complex than you'd think because adb doesn't actually # return the return code from a process, so we have to capture the output # to get it # FIXME: this function buffers all output of the command into memory, # always. :( cmdline = " ".join(cmd) + "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout proc = subprocess.Popen(["adb", "shell", cmdline], stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return return_code return None
def shell(self, cmd, outputfile, env=None, cwd=None): # FIXME: this function buffers all output of the command into memory, # always. :( # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it cmdline = "%s; echo $?" % self._escapedCommandLine(cmd) # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args=[self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): """ Executes shell command on device. Returns exit code. cmd - Command string to execute outputfile - File to store output env - Environment to pass to exec command cwd - Directory to execute command from timeout - specified in seconds, defaults to 'default_timeout' root - Specifies whether command requires root privileges """ # FIXME: this function buffers all output of the command into memory, # always. :( # If requested to run as root, check that we can actually do that if root and not self.haveRootShell and not self.haveSu: raise DMError("Shell command '%s' requested to run as root but root " "is not available on this device. Root your device or " "refactor the test/harness to not require root." % self._escapedCommandLine(cmd)) # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it if root and not self.haveRootShell: cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd) else: cmdline = self._escapedCommandLine(cmd) cmdline += "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join(map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args=[self.adbPath] if self.deviceSerial: args.extend(['-s', self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if not timeout: # We are asserting that all commands will complete in this time unless otherwise specified timeout = self.default_timeout timeout = int(timeout) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: time.sleep(1) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for shell call") (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip('\n')) lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): """ Executes shell command on device. cmd - Command string to execute outputfile - File to store output env - Environment to pass to exec command cwd - Directory to execute command from timeout - specified in seconds, defaults to 'default_timeout' root - Specifies whether command requires root privileges returns: success: Return code from command failure: None """ cmdline = self._escapedCommandLine(cmd) if env: cmdline = '%s %s' % (self._formatEnvString(env), cmdline) haveExecSu = (StrictVersion(self.agentVersion) >= StrictVersion('1.13')) # Depending on agent version we send one of the following commands here: # * exec (run as normal user) # * execsu (run as privileged user) # * execcwd (run as normal user from specified directory) # * execcwdsu (run as privileged user from specified directory) cmd = "exec" if cwd: cmd += "cwd" if root and haveExecSu: cmd += "su" try: if cwd: self._sendCmds([{ 'cmd': '%s %s %s' % (cmd, cwd, cmdline) }], outputfile, timeout) else: if (not root) or haveExecSu: self._sendCmds([{ 'cmd': '%s %s' % (cmd, cmdline) }], outputfile, timeout) else: # need to manually inject su -c for backwards compatibility (this may # not work on ICS or above!!) # (FIXME: this backwards compatibility code is really ugly and should # be deprecated at some point in the future) self._sendCmds([{ 'cmd': '%s su -c "%s"' % (cmd, cmdline) }], outputfile, timeout) except AgentError: return None # dig through the output to get the return code lastline = _pop_last_line(outputfile) if lastline: m = re.search('return code \[([0-9]+)\]', lastline) if m: return int(m.group(1)) # woops, we couldn't find an end of line/return value return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): # FIXME: this function buffers all output of the command into memory, # always. :( # If requested to run as root, check that we can actually do that if root and not self._haveRootShell and not self._haveSu: raise DMError( "Shell command '%s' requested to run as root but root " "is not available on this device. Root your device or " "refactor the test/harness to not require root." % self._escapedCommandLine(cmd)) # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it if root and not self._haveRootShell: cmdline = "su -c \"%s\"" % self._escapedCommandLine(cmd) else: cmdline = self._escapedCommandLine(cmd) cmdline += "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = '; '.join( map(lambda x: 'export %s=%s' % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args = [self._adbPath] if self._deviceSerial: args.extend(['-s', self._deviceSerial]) args.extend(["shell", cmdline]) procOut = tempfile.SpooledTemporaryFile() procErr = tempfile.SpooledTemporaryFile() proc = subprocess.Popen(args, stdout=procOut, stderr=procErr) if not timeout: # We are asserting that all commands will complete in this time unless otherwise specified timeout = self.default_timeout timeout = int(timeout) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: time.sleep(self._pollingInterval) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for shell call") procOut.seek(0) outputfile.write(procOut.read().rstrip('\n')) procOut.close() procErr.close() lastline = _pop_last_line(outputfile) if lastline: m = re.search('([0-9]+)', lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None
def shell(self, cmd, outputfile, env=None, cwd=None, timeout=None, root=False): """ external function: executes shell command on device. timeout is specified in seconds, and if no timeout is given, we will run until we hit the default_timeout specified in __init__ returns: success: <return code> failure: None """ # FIXME: this function buffers all output of the command into memory, # always. :( # Getting the return code is more complex than you'd think because adb # doesn't actually return the return code from a process, so we have to # capture the output to get it if root: cmdline = 'su -c "%s"' % self._escapedCommandLine(cmd) else: cmdline = self._escapedCommandLine(cmd) cmdline += "; echo $?" # prepend cwd and env to command if necessary if cwd: cmdline = "cd %s; %s" % (cwd, cmdline) if env: envstr = "; ".join(map(lambda x: "export %s=%s" % (x[0], x[1]), env.iteritems())) cmdline = envstr + "; " + cmdline # all output should be in stdout args = [self.adbPath] if self.deviceSerial: args.extend(["-s", self.deviceSerial]) args.extend(["shell", cmdline]) proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE) if not timeout: # We are asserting that all commands will complete in this time unless otherwise specified timeout = self.default_timeout timeout = int(timeout) start_time = time.time() ret_code = proc.poll() while ((time.time() - start_time) <= timeout) and ret_code == None: time.sleep(1) ret_code = proc.poll() if ret_code == None: proc.kill() raise DMError("Timeout exceeded for shell call") (stdout, stderr) = proc.communicate() outputfile.write(stdout.rstrip("\n")) lastline = _pop_last_line(outputfile) if lastline: m = re.search("([0-9]+)", lastline) if m: return_code = m.group(1) outputfile.seek(-2, 2) outputfile.truncate() # truncate off the return code return int(return_code) return None