How to open adb shell and execute commands inside shell using python - android

I am trying to execute adb shell commands in python using subprocess.Popen
Example: Need to execute 'command' in adb shell. While executing manually, I open the command window and execute as below and it works.
>adb shell
#<command>
In Python I am using as below but the process is stuck and doesn't give output
subprocess.Popen('adb shell <command>)
Tried executing manually in command window, same result as python code,stuck and doesn't give output
>adb shell <command>
I am trying to execute a binary file in background(using binary file name followed by &) in the command.

Found a way to do it using communicate() method in subprocess module
procId = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
procId.communicate('command1\ncommand2\nexit\n')

use pexpect (https://pexpect.readthedocs.io/en/stable/)
adb="/Users/lishaokai/Library/Android/sdk/platform-tools/adb"
import pexpect
import sys, os
child = pexpect.spawn(adb + " shell")
child.logfile_send = sys.stdout
while True:
index = child.expect(["$","#",pexpect.TIMEOUT])
print index
child.sendline("ls /storage/emulated/0/")
index = child.expect(["huoshan","google",pexpect.TIMEOUT])
print index, child.before, child.after
break

Ankur Kabra, try the code below:
#!/usr/bin/env python
# -*- coding: utf-8 -*-
import subprocess
command = 'adb devices'
p = subprocess.Popen(command, shell=True,
stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
print 'standard output: %s \n error output: %s \n',(stdout,stderr)
and you will see the error output.
Usually it will tell you:
/bin/sh: adb: command not found
which means, shell can not excute adb command.
so, adding adb to your PATH or writing the full path of adb will solve the problem.
May help.

Related

How to read all files name in a dir under adb shell model

I tend to read files name in a Android device beacuse I want to check the resource in this device is correct. Normally the order of manual testing is
adb -s 192.168.1.100:5555 root
adb -s 192.168.1.100:5555 shell
and when enter shell model, into the dir and ls
cd xxx\xxx\xxx
ls
Now I tend to write a python script to help me check it, so I try:
os.system('adb -s 192.168.1.100:5555 root')
obj = subprocess.Popen(["adb -s 192.168.1.100:5555 shell"], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
and then I dont't know how to read file name and put file name into a list. Without shell model I try:
file_list = os.listdir("xxx\xxx\xxx")
l = []
for file_name in file_list:
l.append(file_name)
It works, but how can I do this in shell model? I mean switch path to adb shell path, then I can use this code to put file name into a list. Any idea? Thanks!
If you want to print all the files in a particular directory in a shell, you can simply try this:
for i in *; do echo $i;done
Here is what you can put in your python file.
import subprocess
p = subprocess.Popen('for i in *; do echo $i;done', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
This will get your task done.

Launch adb commands in python

I try launch adb commands in python without custom modules.
try:
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, shell=True)
process.stdin.write("adb shell uninstall com.q.q".encode("utf8"))
process.stdin.write("adb shell install C:\\...\\qwerty.apk".encode("utf8"))
but this not working. Code finish without results
cannot test with your exact commands but that works fine:
import subprocess
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None, shell=True)
o,e = process.communicate(b"dir\n")
print(o)
(I get the contents of my directory)
so for your example, you're missing the line terminators when sending commands. The commands aren't issued to the cmd program, the pipe is broken before that.
That would work better:
import subprocess
process = subprocess.Popen('cmd.exe', stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=None)
process.stdin.write(b"adb shell uninstall com.q.q\n")
process.stdin.write(b"adb shell install C:\\...\\qwerty.apk\n")
o,e = process.communicate()
but this is a very strange way to run commands. Just use check_call, with args split properly:
subprocess.check_call(["adb","shell","uninstall","com.q.q"])
subprocess.check_call(["adb","shell","install",r"C:\...\qwerty.apk"])

How to run two adb shell commands via Python, but store output of only one?

I am [new to] using Python 2.7 on Windows 7 and I am trying to incorporate adb shell commands to access/change the directories on my Android device. What I need to do is get the size of a directory in Internal Storage, save that output as a variable, and then delete the directory. From my research I believe I should be using subprocess.Popen()to create the shell and then .communicate() to send the required commands. However I am currently only able to execute one of the commands: delete the directory. Below is the code that I used:
import os, subprocess
from subprocess import PIPE, Popen
adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
adb_shell.communicate('cd /sdcard\nrm -r "Directory to Delete"\nexit\n')
However, if I add another command by doing:
adb_shell.communicate('cd /sdcard\ndu -sh "Directory A"\nrm -r "Directory A"\nexit\n')
It does not work because I need to incorporate stdout = subprocess.PIPE to store the output of the du -sh "Directory A"command, but how do I go about doing that? If I add it like: adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE, stdout = subprocess.PIPE), it does not work. Any suggestions? ty!
Edit: The closest I've come to a solution (actually getting an output in the interpreter and removing the file afterwards) is with:
adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE, stdout = subprocess.PIPE)
adb_shell.communicate('cd /sdcard\ndu -sh "qpython"\nexit\n')
output = adb_shell.stdout
print output
adb_shell = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
adb_shell.communicate('cd /sdcard\nrm -r "qpython"\nexit\n')
Which has an output of: '', mode 'rb' at 0x02B4D910>'
It's not pretty but it works:
lines = []
get_restore_size = subprocess.Popen('adb shell du -sh /sdcard/qpython', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in get_restore_size.stdout.readlines():
lines.append(line)
restore_size = (lines[0].strip('\t/sdcard/qpython\r\r\n'))
print restore_size
del_restore = subprocess.Popen('adb shell', stdin = subprocess.PIPE)
del_restore.communicate('cd /sdcard\nrm -r "qpython"\nexit\n')
Open to suggestions to improve!
There is no reason for running both commands in the same shell session:
print subprocess.check_output(["adb", "shell", "du -sh /sdcard/qpython"])
subprocess.check_output(["adb", "shell", "rm -r /sdcard/qpython"])

Popen shell commands and | pipe symbol

I have checked out numerous other threads with the same issue, but cannot get one that works for me.
I am trying to run a command using the | character on a Windows machine, with python and wx.python. Command I'm trying to run is: adb.exe logcat | findstr myApp (stored in pkgName)
I have tried the following with no success, nothing is written in 'progressBox': note: they weren't all tried at the same time ;)
logcat = subprocess.Popen(toolsDir + "\\adb.exe logcat", stdout=subprocess.PIPE)
findstr = subprocess.Popen("findstr '"+ pkgName+"'", stdin=logcat.stdout, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = findstr.communicate()
cmd = toolsDir+"\\adb.exe logcat | findstr " + pkgName
ps = subprocess.Popen(cmd,shell=True,stdout=subprocess.PIPE,stderr=subprocess.STDOUT)
stdout = ps.communicate()[0]
c_arg = 'logcat | findstr ' + pkgName
params = toolsDir + "\\adb.exe " + c_arg
p = Popen(params, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
stdout, stderr = p.communicate()
They are all slightly different, but none append to my progressBox to print out the output.
self.progressBox.AppendText(stdout)
self.progressBox.AppendText(stderr)
I have myself faced issue numerous times using subprocess library to run system command. I would probably recommend using core os library, still i am not very sure if this will work on windows but you could give a try.
import os
cmd = "ls -la > output.txt"
os.system(cmd)
reader = open("output.txt")
print(reader.read())
PS: It is recommended to use subprocess module to run system command, you should use above code only when you are unable to find a solution and just want to run code urgently.

Why does adb push/pull redirect STDOUT to STDERR?

When using 'adb pull ...' the output is sent to stderr regardless of success. Is there any reason for this? For an example, pulling a file that is there and pulling a file that doesn't exist:
When I run:
adb pull /data/data/good_file.txt /tmp`
I get the following:
stdout:
stderr: 0 KB/s (13 bytes in 0.078s)
(i.e. no stdout)
Then when when I run:
adb pull /data/data/bad_file.txt /tmp
I get the following:
stdout:
stderr: remote object '/data/bad_file.txt' does not exist
The program below was used to generate the above results:
from subprocess import Popen
cmd = "adb pull /data/data/good_file.txt /tmp"
p = Popen(cmd.split(), stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()
print cmd
print "stdout: " + out
print "stderr: " + err
I have the same issue with: adb install -r /foo/bar.apk and sound like adb always send his result to stderr, just add 2>&1 at end and it solves the problem.
cmd = "adb pull /data/data/good_file.txt /tmp 2>&1"
The 2>&1 just redirects Channel 2 (Standard Error) and Channel 1
(Standard Output) to the same place which in this context is Channel 1
(Standard Output), and thence your log file.

Categories

Resources