《自拍教程40》Python adb一鍵導出Log

Android設備,比如車載系統實車路試過程中,
車上操作電腦比較麻煩,如果車載系統出現了Bug,
如何很方便地一次性導出相關的log來(logcat, dbus, 高德地圖log,gps定位log等)來呢?
其實我們只需要一個python腳本就可以搞定!


準備階段
  1. adb pull 命令, 可以把Android系統裏的文件,pull到電腦端
  2. 導出的Log,需要在當前路徑新建一個文件夾用於存放,最好以時間戳命名
  3. os.system()可以調用adb命令

Android車載系統默認的Log存儲路徑
Android Log類型 默認路徑
logcat序列log /data/logs/logcat.txt
/data/logs/logcat.txt.1

/data/logs/logcat.txt.20
dbus序列log /data/logs/dbus.txt
/data/logs/dbus.txt.1

/data/logs/dbus.txt.20
kernel序列log /data/logs/kernel.txt
/data/logs/kernel.txt.1

/data/logs/kernel.txt.20
tombstone log /data/tombstones/*
anr卡死log /data/anr/*
dropbox log /data/system/dropbox/*
gps log /sdcard/map/gps/*
高德地圖log /sdcard/amapauto8/logs/*

自動生成的序列Log

何爲自動生成的序列log,一般系統啓動過程中,
就默認開啓了某種類型的log,且序列化存儲,新的會自動沖刷掉舊的log。


比如logcat序列log,
一般是全部寫到logcat.txt,寫滿5M後,
將logcat.txt重命名爲logcat.txt.1,以此類推。。。
所以logcat.txt就始終是最新的log,
然後就是logcat.txt.1,
再然後是logcat.txt.2,

最後是到序列logcat.txt.20


當然以上取決於init.rc裏的關於logcat自啓動命令的設置,
比如init.rc配置文件,如果設置如下:

/system/bin/logcat -b system -b events -b main
-b radio -n 20 -r5000 -v threadtime -f /data/logs/logcat.txt

以上啓動命令則表示:截取所有包括system,events,main,radio四種緩衝區的logcat 日誌,
並設置自動序列爲20個序列片段,-r5000 代表是5M一個,
-v threadtime是打印線程級別的時間戳,
-f 是輸出到什麼路徑,logcat.txt是初始和默認的句柄文件。


其他的dbus.txt序列log, kernel序列log也是一致的。
如以下截圖所示:


Python批處理腳本模式
# coding=utf-8

import os
from datetime import datetime

# 先新建一個帶時間戳的文件夾用於存放導出來的Log
now_time = datetime.now().strftime("%Y%m%d_%H%M%S")
log_folder = "Logs_" + now_time
os.mkdir(log_folder)  # 因爲沒指定具體路徑,默認就是在當前路徑下創建。

# 先導出所有序列log
os.system("adb pull /data/logs/logcat.txt %s" % log_folder)
os.system("adb pull /data/logs/dbus.txt %s" % log_folder)
os.system("adb pull /data/logs/kernel.txt %s" % log_folder)
for i in range(1, 21):
    os.system("adb pull /data/logs/logcat.txt.%s %s" % (i, log_folder))
    os.system("adb pull /data/logs/dbus.txt.%s %s" % (i, log_folder))
    os.system("adb pull /data/logs/kernel.txt.%s %s" % (i, log_folder))

# 再導出其他log
os.system("adb pull /data/tombstones %s" % log_folder)
os.system("adb pull /data/anr %s" % log_folder)
os.system("adb pull /data/system/dropbox %s" % log_folder)
os.system("adb pull /sdcard/map/gps %s" % log_folder)
os.system("adb pull /sdcard/amapauto8/logs %s" % log_folder)

# 打印存放地址的絕對路徑。
print("所有實車log均已經導出,存放地址:%s" % os.path.abspath(log_folder))

os.system("pause")

Python面向過程函數形式

我們可以再細分爲5個函數,
其中1個函數是創建帶時間戳的文件夾的,
其中1個函數是導出logcat.txt序列log的,
其中1個函數是導出dbus.txt序列log的,
其中1個函數是導出kernel.txt序列log的,
最後1個函數是導出所有包含其他log的函數。

# coding=utf-8

import os
from datetime import datetime

# 先新建一個帶時間戳的文件夾用於存放導出來的Log
def creat_floder():
    now_time = datetime.now().strftime("%Y%m%d_%H%M%S")
    log_folder = "Logs_" + now_time
    os.mkdir(log_folder)  # 因爲沒指定具體路徑,默認就是在當前路徑下創建。
    return os.path.abspath(log_folder)  # 返回絕對路徑

# 導出logcat序列log
def pull_logcat_logs(save_path):
    os.system("adb pull /data/logs/logcat.txt %s" % save_path)
    for i in range(1, 21):
        os.system("adb pull /data/logs/logcat.txt.%s %s" % (i, save_path))

# 導出dbus序列log
def pull_dbus_logs(save_path):
    os.system("adb pull /data/logs/dbus.txt %s" % save_path)
    for i in range(1, 21):
        os.system("adb pull /data/logs/dbus.txt.%s %s" % (i, save_path))

# 導出kernel序列log
def pull_kernel_logs(save_path):
    os.system("adb pull /data/logs/kernel.txt %s" % save_path)
    for i in range(1, 21):
        os.system("adb pull /data/logs/kernel.txt.%s %s" % (i, save_path))

def pull_all_logs(save_path):
    pull_logcat_logs(save_path)  # 函數調用
    pull_dbus_logs(save_path)    # 函數調用
    pull_kernel_logs(save_path)  # 函數調用
    os.system("adb pull /data/tombstones %s" % save_path)
    os.system("adb pull /data/anr %s" % save_path)
    os.system("adb pull /data/system/dropbox %s" % save_path)
    os.system("adb pull /sdcard/map/gps %s" % save_path)
    os.system("adb pull /sdcard/amapauto8/logs %s" % save_path)
    # 打印存放地址的絕對路徑。
    print("所有實車log均已經導出,存放地址:%s" % save_path)

log_path = creat_floder()
pull_all_logs(log_path)
os.system("pause")

以上,實現了函數的返回值, 並傳參,及函數內嵌調用。

Python面向對象類的形式
  1. 以"萬物皆可歸類"的思想, 先抽象化出一個類來,
    類名一般建議用"名詞", 所以我們命名爲"LogPuller",
    代表Log導出器, 且一般要駝峯式(首字母大寫)來規範類的命名。
  2. 養成良好的類的初始化(__init__)的習慣,
    初始化過程中, 可以傳入導出的路徑。
  3. 這個LogPuller類, 建議是再細化各類型Log的導出函數。
  4. 類是一個抽象的事物, 必須實例化成具體的對象後,
    才能進行調用, 所以我們實例化並命名成了l_obj, 表明是一個對象。
  5. 實例化成具體對象後, 對象就可以調用pull_all_logs這個函數了
# coding=utf-8

import os
from datetime import datetime


# 先新建一個帶時間戳的文件夾用於存放導出來的Log
# 這個作爲一個公用函數,不放到類裏,單獨以函數的形式存在
def creat_floder():
    now_time = datetime.now().strftime("%Y%m%d_%H%M%S")
    log_folder = "Logs_" + now_time
    os.mkdir(log_folder)  # 因爲沒指定具體路徑,默認就是在當前路徑下創建。
    return os.path.abspath(log_folder)


# 導出所有實車日誌
class LogPuller():
    def __init__(self, save_path):
        self.save_path = save_path

    # 導出logcat序列log
    def pull_logcat_logs(self):
        os.system("adb pull /data/logs/logcat.txt %s" % self.save_path)
        for i in range(1, 21):
            os.system("adb pull /data/logs/logcat.txt.%s %s" % (i, self.save_path))

    # 導出dbus序列log
    def pull_dbus_logs(self):
        os.system("adb pull /data/logs/dbus.txt %s" % self.save_path)
        for i in range(1, 21):
            os.system("adb pull /data/logs/dbus.txt.%s %s" % (i, self.save_path))

    # 導出kernel序列log
    def pull_kernel_logs(self):
        os.system("adb pull /data/logs/kernel.txt %s" % self.save_path)
        for i in range(1, 21):
            os.system("adb pull /data/logs/kernel.txt.%s %s" % (i, self.save_path))

    def pull_tombstones_logs(self):
        os.system("adb pull /data/tombstones %s" % self.save_path)

    def pull_anr_logs(self):
        os.system("adb pull /data/anr %s" % self.save_path)

    def pull_dropbox_logs(self):
        os.system("adb pull /data/system/dropbox %s" % self.save_path)

    def pull_gps_logs(self):
        os.system("adb pull /sdcard/map/gps %s" % self.save_path)

    def pull_amapauto_logs(self):
        os.system("adb pull /sdcard/amapauto8/logs %s" % self.save_path)

    def pull_all_logs(self):
        self.pull_logcat_logs()
        self.pull_dbus_logs()
        self.pull_kernel_logs()
        self.pull_tombstones_logs()
        self.pull_anr_logs()
        self.pull_dropbox_logs()
        self.pull_gps_logs()
        self.pull_amapauto_logs()
        # 打印存放地址的絕對路徑。
        print("所有實車log均已經導出,存放地址:%s" % self.save_path)

# 更科學的文件內運行方式
if __name__ == '__main__':
    log_path = creat_floder()
    l_obj = LogPuller(log_path)
    l_obj.pull_all_logs()
    os.system("pause")

代碼運行方式

確保Android車機設備通過USB線與電腦連接了,adb設備有效連接,
以上代碼的3種實現形式都可以直接運行,比如保存爲pull_logs.py並放在桌面,
每次需要截圖的時候,雙擊運行pull_logs.py,
就會在當前文件夾下生成一個類似:Logs_20200308_101503的文件夾。

更多更好的原創文章,請訪問官方網站:www.zipython.com
自拍教程(自動化測試Python教程,武散人編著)
原文鏈接:https://www.zipython.com/#/detail?id=884c9f1c4f2e4a159457d7993d723aec
也可關注“武散人”微信訂閱號,隨時接受文章推送。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章