Python can not capture full adb logs - android

What I want to achieve -
running adb log (logs are running),
doing some activity on android,
stop/end log capture (ctrl+c),
post processing of logs.
Only issue which i face -
can not capture full logcat log in file
import sys
import subprocess
import time
import ctypes
# start
print "test start"
time.sleep(5)
# log capturing start, log does not stop it will keep on running
proc = subprocess.Popen("adb logcat -v time",stdout=subprocess.PIPE )
time.sleep(3) # just so it runs for a while
print "calc start"
time.sleep(5)
#START test************************************
Some code for testing
#CTRL C*************************************************
try:
ctypes.windll.kernel32.GenerateConsoleCtrlEvent(0, 0)
proc.wait()
except KeyboardInterrupt:
print "ignoring ctrlc"
print "still running"
#********************adb log saving******************
text = proc.stdout.read()
f = open('C:\Python27\out_logs_dd\log.txt', 'w')
f.write(text)
with open('C:\Python27\out_logs_dd\log.txt', 'w') as f:
f.write(text)
f.close()
When I run this code, everything is running but log size is so small.
I searched and came to know that "proc.communicate()"might be the solution.
I tried 'communicate' but could not solve the issue.
any help pointer pls.

Replacing proc.stdout.read() with proc.stdout.readline() solved it for me. stdout.read() reads everything until EOF - slowing down the speed drastically. A similar question: Communicate with subprocess without waiting for the subprocess to terminate on windows

you can use adb shell logcat instead of abd logcat in
proc = subprocess.Popen("adb shell logcat -v time",stdout=subprocess.PIPE)
it will give all logs.
i hope it will work.

Related

Unable to log into file using logcat running from script as a service in AOSP 5.1

I am trying to log to a file from custom shell script started as service using init.project.rc. On using below lines in the script(ethmon.sh), i am unable to log it to file test.txt. It is not even creating the file. Any hints on this?
ethmon.sh
mkdir /data/local/tmp/test 2>/dev/null
echo "Issue Observed with IP at `date`" >> /data/local/tmp/test/test.txt
dmesg >> /data/local/tmp/test/test.txt
timeout -t 10 logcat -v time -f /data/local/tmp/test/logcat.txt
init.project.rc
service ethmon /system/xbin/ethmon
class main
user root
group root
oneshot
on property:dev.bootcomplete=1
start ethmon
preload_script.sh
cp -f $SOURCE_FOLDER/ethmon.sh $OUT/system/xbin/ethmon
I am new to aosp, am i missing some permissions to be added for this.
NOTE: Other lines of code(ifconfig eth0 down/up, netcfg) is working fine in the same script.
Finally i added selinux permissions and created .te file for my service to get the log thing working. Thanks https://stackoverflow.com/users/12098405/dash-o for the help. People with same issue can comment for any further information.

subprocess.check_output fails to execute a command but the same works in windows

I am trying to connect two devices to my pc and run some commands on them using python and adb.
when I run the command from the command prompt, it goes through fine, but when i put those in the python script, they give me errors.
this is causing the errors all the time:
from subprocess import check_output, CalledProcessError
try:
adb_ouput = check_output(["adb","devices","-l","|", "grep", "\"model\""])
print adb_ouput
except CalledProcessError as e:
print e
The error message I get is this:
Usage: adb devices [-l]
Command '['adb', 'devices', '-l', '|', 'grep', '"model"']' returned non-zero exit status 1
When I try the same code without the grep command, it works
adb_ouput = check_output(["adb","devices","-l"])
It gives me the right output.
When I try the same in windows command prompt, It works fine (I am replacing grep with FINDSTR because i'm using it in windows, and I have tried doing the same in the python script as well, with 'shell = True' and also without.)
eg:
adb devices -l | FINDSTR "model"
This gives me an ouptut without any problems.
The output I get is
123ab6ef device product:xxxxxxxxx model:xxxxxxxxx device:xxxxxxxxx
bd00051a4 device product:yyyyyyyyyy model:yyyyyyyyyy device:yyyyyyyyy
I am trying to understand where I am going wrong here, but can't figure it out.
So far I have checked the docs: https://docs.python.org/3/library/subprocess.html
https://docs.python.org/3/library/subprocess.html#subprocess.CalledProcessError
These just give me the error codes.
I have also looked at these answers:
Python, adb and shell execution query
I took some error checking from here and added to my code.
Python subprocess.check_output(args) fails, while args executed via Windows command line work OK
python check_output fails with exit status 1 but Popen works for same command
I think i am close but just can't put my finger on it.
Any help would be appreciated.
First
adb_ouput = check_output(["adb","devices","-l","|", "grep", "\"model\""])
certainly requires shell=True, but even with that it's not equivalent to
adb devices -l | FINDSTR "model"
When using check_output, you're passing "model" as grep argument literally but you should pass just model. "model" is not in your output (with quotes) so grep fails to find it, and returns exitcode 1 which is not really an error for grep but makes check_output trigger an exception because it expects 0.
So I would to this as a quickfix:
adb_ouput = check_output(["adb","devices","-l","|", "grep", "model"],shell=True)
And as a longfix I'd perform the grep command directly with python.
adb_output = check_output(["adb","devices","-l"])
for l in adb_output.splitlines():
if "model" in l:
print(l)

Python - How to hide output after killed specified process

now i try to create a python script to get Android logcats automatically
below seciton is part of my codes
logcat_process = subprocess.Popen('adb logcat -v time > logcat.log', shell=True)
time.sleep(5)
os.kill((logcat_process.pid)+1, signal.SIGKILL)
however, every time after os.kill terminate the process,
it will print message like
"/bin/sh: line 1: 13961 Killed: 9 adb logcat -v time > logcat.log"**
on the screen.
Does anybody have any idea how to hide this message?
I want the result print of script more simple and clear....
You can do something like this:
logcat_process = subprocess.Popen('adb logcat -v time > logcat.log', shell=True)
time.sleep(5)
save_stdout = sys.stdout
sys.stdout = open(r'/youlib..../trash.txt', 'w')
os.kill((logcat_process.pid)+1, signal.SIGKILL)
# regain stdout to screen
sys.stdout.close()
sys.stdout = save_stdout
It will divert the stdout to the trash.txt file at the kill operation.
redirect the stdout/stderr in python and add a filter.

ADB Error codes

We have an android device and as part of testing I need to excute a console test application on the target device. If the test application detects an error it returns -1.
I can use adb shell to run the test applications remotely on the target but I can't find a way of getting back the return code. I need this so I that I can build this into an automated test suite.
I could try grepping the console output for some failure text but that is a bit grubby. Does anyone know of a more elegant solution?
This is a workaround to get the exit code:
adb shell '{your command here} > /dev/null 2>&1; echo $?'
This is a wrapper around adb in Ruby:
def adb(opt)
input = "#{adb_command} #{opt[:command]} #{opt[:params]}"
puts "Executing #{input}...\n"
output = nil
exit_code = 0
def wait_for(secs)
if secs
begin
Timeout::timeout(secs) { yield }
rescue
print 'execution expired'
end
else
yield
end
end
wait_for(opt[:timeout]) do
case opt[:command]
when :install, :push, :uninstall
output, exit_code = `#{input}`, $?.to_i
when :shell
input = "#{adb_command} shell \"#{opt[:params]}; echo \\$?\""
output = `#{input}`.split("\n")
exit_code = output.pop.to_i
output = output.join("\n")
else
raise 'Error: param command to adb not defined!'
end
end
return if opt[:ignore_fail] and output =~ /#{opt[:ignore_fail]}/
raise output unless exit_code == 0
end
You could use Facebook's fb-adb, a "A better shell for Android devices" which "propagates program exit status instead of always exiting with status 0".

Trying to output my LogCat to a file

I've been told it's a command line option. But Eclipse's Run!Run Configurations...!Target!Additional Emulator Command Line Options field is already occupied with
-sdcard "C:\android-sdk-windows\tools\sd9m.img"
If I wanted to write something like
adb logcat -s MessageBox > "C:\Users\me\Documents\LogCatOutput.txt"
then where do I write it, and how (i.e., is the syntax even correct)? I need to output only a filtered tag, not verbose. ("MessageBox" is my TAG. Again I don't know if any of this punctuation is right, or even where the command goes.)
Thanks for any help.
There should be an adb.exe file in C:\android-sdk-windows\tools. You can invoke this manually from a DOS command prompt:
cd C:\android-sdk-windows\tools
adb logcat -s MessageBox > "C:\Users\me\Documents\LogCatOutput.txt"
There's no need to bother with Eclipse in this case.
Alternatively, if you only want to dump whatever's already in the logcat buffers and exit immediately (useful for scripts), you can specify the -d option:
$ adb logcat -d -s MessageBox > dump_file.txt
Make sure that '-d' is after 'logcat'.
Another useful addition to the above answers is filtering. The application I am working on generates a massive amount of logging, so it is useful to log with filters.
adb -s MyDevice logcat | find /V ": T#" > d:\temp\logcat.txt
or for OSX/Linux
adb -s MyDevice logcat | grep -v ": T#" > ~/logcat.txt
This will write all logcat activity apart from any line that contains ": T#"
find or grep can also be used to filter based on positive results. I then use the likes of BareTail display the growing log file.

Categories

Resources