一属韧、前言
logcat 作為讀取日志的工具楼镐,相當(dāng)于client 的角色忿族;在前兩篇文章中,關(guān)于 logcat 如何與其他部分溝通獲取日志信息的流程已經(jīng)介紹的比較清晰驻啤,本文不在贅述菲驴,轉(zhuǎn)而歸納一下 logcat 的一些常用指令,并對(duì)其中一些做詳細(xì)分析
二骑冗、命令簡(jiǎn)介
選項(xiàng) | 描述 | eg |
---|---|---|
-s | 輸出指定 tag 的日志赊瞬,相當(dāng)于過濾器表達(dá)式 '*:S' | logcat -s tag |
-f <file> | 設(shè)置logcat 內(nèi)容保存的位置先煎,默認(rèn)是stdout | logcat -f sdcard/log.txt |
-r <kbytes> | 每輸出 <kbytes> 時(shí)輪替日志文件,默認(rèn)是16 必須配合 -f (暫不明白) | logcat -f sdcard/log.txt -r 1 |
-n <count> | 設(shè)置日志輸出的最大數(shù)目, 需要 -r 參數(shù) | 暫不明白 |
-v <format> | 設(shè)置日志消息的輸出格式巧涧。詳見下文 格式化輸出 | logcat -v thread |
-D | 輸出各個(gè)日志緩沖區(qū)之間的分隔線 | logcat -D ... |
-c | 清除(清空)所選的緩沖區(qū)并退出榨婆,默認(rèn)清除 main、system 和 crash | logcat -c / -b all -c |
-d | 將日志轉(zhuǎn)儲(chǔ)到屏幕并退出 | logcat -d > log.txt |
-e <expr> | 輸出正則匹配的日志消息 | logcat -e 匹配數(shù)據(jù) -m 5 |
-m <count> | 輸出 <count> 行后退出 | ...... |
-t <count> | 僅輸出最新的行數(shù)褒侧,此選項(xiàng)包括 -d 功能 | logcat -t 5 |
-t '<time>' | 輸出自指定時(shí)間以來的最新行良风,此選項(xiàng)包括 -d 功能 | logcat -t '01-26 20:52:41.820' |
-g | 獲取指定日志緩沖區(qū)的大小并退出 | logcat -g |
-G | 設(shè)置日志環(huán)形緩沖區(qū)的大小,可以在結(jié)尾處添加 K 或 M | logcat -G 2M |
-b | 加載可供查看的日志緩沖區(qū)闷供,更多可見下文 日志緩沖區(qū) | logcat -b system |
-B | 以二進(jìn)制文件形式輸出日志 | ...... |
-S | 在輸出中包含統(tǒng)計(jì)信息烟央,以識(shí)別和定位日志垃圾信息發(fā)送者 | ...... |
--pid=<pid> | 僅輸出來自給定 PID 的日志 | logcat --pid=4355 |
三、日志緩沖區(qū)
Android 日志系統(tǒng)為日志消息保留了多個(gè)環(huán)形緩沖區(qū)歪脏,但并非多有的日志消息都會(huì)發(fā)送到默認(rèn)的環(huán)形緩沖區(qū)疑俭。這里可以采用 logcat -b 命令查看設(shè)備的其他緩沖區(qū):
緩沖區(qū) | 描述 | eg |
---|---|---|
radio | 輸出通信系統(tǒng)的日志,包含無線裝置/電話相關(guān)消息 | logcat -b radio |
events | 輸出event模塊的日志 | logcat -b events |
main | 主日志緩沖區(qū)(默認(rèn))婿失,不包含系統(tǒng)和崩潰日志消息 | logcat -b main |
system | 輸出系統(tǒng)日志 | logcat -b system |
crash | 輸出崩潰日志 | logcat -b crash |
all | 輸出所有緩沖區(qū)日志 | logcat -b all |
default | 輸出main钞艇、system、crash緩沖區(qū)日志 | logcat -b default |
如果需要查看內(nèi)核空間日志信息豪硅,可采用如下幾種方式查看:
1哩照、讀取 /proc/kmsg ,命令如下
adb shell cat /proc/kmsg
讀取/proc/kmsg屬于消費(fèi)型讀取懒浮,讀取之后再次讀取不會(huì)顯示已經(jīng)讀取過的日志信息
2飘弧、讀取 /dev/kmsg,命令如下
adb shell cat /dev/kmsg
讀取/dev/kmsg會(huì)顯示緩存區(qū)里面的所有日志信息砚著。新寫入的日志信息會(huì)不斷累加到日志緩沖器中
3次伶、使用 dmesg 命令讀取
adb shell dmesg
dmesg命令讀取一次只顯示一部分日志,非阻塞執(zhí)行
四、格式化輸出
使用 -v 命令來修改 log 的輸出格式稽穆,以顯示特定的元數(shù)據(jù)字段:
格式 | 描述 | eg |
---|---|---|
brief | 顯示優(yōu)先級(jí)冠王、標(biāo)記以及發(fā)出消息的進(jìn)程的 PID | ...... |
long | 顯示所有元數(shù)據(jù)字段,并使用空白行分隔消息 | ...... |
process | 僅顯示 PID | ...... |
raw | 顯示不包含其他元數(shù)據(jù)字段的原始日志消息 | ...... |
tag | 僅顯示優(yōu)先級(jí)和標(biāo)記 | ...... |
thread | 舊版格式舌镶,顯示優(yōu)先級(jí)柱彻、PID 以及發(fā)出消息的線程的 TID | ...... |
threadtime | (默認(rèn)值)顯示日期、調(diào)用時(shí)間乎折、優(yōu)先級(jí)绒疗、標(biāo)記侵歇、PID 以及發(fā)出消息的線程的 TID | ...... |
time | 顯示日期骂澄、調(diào)用時(shí)間、優(yōu)先級(jí)惕虑、標(biāo)記以及發(fā)出消息的進(jìn)程的 PID | ...... |
color | 使用不同的顏色來顯示每個(gè)優(yōu)先級(jí) | ...... |
descriptive | 顯示日志緩沖區(qū)事件說明坟冲。此修飾符僅影響事件日志緩沖區(qū)消息磨镶,不會(huì)對(duì)其他非二進(jìn)制文件緩沖區(qū)產(chǎn)生任何影響 | ...... |
epoch | 顯示自 1970 年 1 月 1 日以來的時(shí)間(以秒為單位) | ...... |
monotonic | 顯示自上次啟動(dòng)以來的時(shí)間(以 CPU 秒為單位) | ...... |
printable | 確保所有二進(jìn)制日志記錄內(nèi)容都進(jìn)行了轉(zhuǎn)義 | ...... |
uid | 如果訪問控制允許,則顯示 UID 或記錄的進(jìn)程的 Android ID | ...... |
usec | 顯示精確到微秒的時(shí)間 | ...... |
UTC | 顯示 UTC 時(shí)間 | ...... |
year | 將年份添加到顯示的時(shí)間 | ...... |
zone | 將本地時(shí)區(qū)添加到顯示的時(shí)間 | ...... |
優(yōu)先級(jí):
選項(xiàng) | 描述 | eg |
---|---|---|
V | –Verbose(最低優(yōu)先級(jí)) | adb logcat *:v |
D | – Debug | adb logcat *:d |
I | – Info | adb logcat *:i |
W | – Warning | adb logcat *:w |
E | – Error | adb logcat *:e |
F | – Fatal | adb logcat *:f |
S | – Silent | adb logcat *:s |
五健提、logcat -f 命令詳解
logcat -f 命令可以將日志消息輸出到指定的文件中琳猫。這里我們需要確定的一件事是 logcat 作為客戶端的角色,會(huì)將通過 liblog 獲得的日志信息進(jìn)行格式解析私痹、格式化處理脐嫂,而 liblog 庫(kù)本身并不存在保存、解析的功能紊遵。這里來對(duì) -f 指令做一下解析:
logcat_main.cpp # main()
---> logcat.cpp # android_logcat_run_command()
---> __logcat()
{
......
case 'f':
if ((tail_time == log_time::EPOCH) && !tail_lines) {
tail_time = lastLogTime(optctx.optarg);
}
// redirect output to a file
context->outputFileName = optctx.optarg; //注釋 ①
break;
......
setupOutputAndSchedulingPolicy() //注釋 ②
while (...) { //注釋 ③
int ret = android_logger_list_read(logger_list, &log_msg);
if (context->printBinary) {
printBinary(context, &log_msg);
} else {
processBuffer(context, dev, &log_msg);
}
......
}
5.1 注釋① :解析 -f 指令
case 'f':
if ((tail_time == log_time::EPOCH) && !tail_lines) {
tail_time = lastLogTime(optctx.optarg);
}
// redirect output to a file
context->outputFileName = optctx.optarg; //注釋 ①
break;
在 _logcat() 函數(shù)中解析 -f 指令账千,設(shè)置日志輸出文件。例如 logcat -f sdcard/log.txt 暗膜,則 context->outputFileName 賦值為 sdcard/log.txt匀奏;
5.2 注釋② :設(shè)置輸出路徑
static void setupOutputAndSchedulingPolicy(
android_logcat_context_internal* context, bool blocking) {
if (!context->outputFileName) return;
......
// 打開文件獲得 fd
context->output_fd = openLogFile(context->outputFileName);
if (context->output_fd < 0) {
logcat_panic(context, HELP_FALSE, "couldn't open output file");
return;
}
......
}
5.3 注釋③ :寫入日志
while (...) {
// 調(diào)用 liblog 庫(kù)中的 android_logger_list_read 函數(shù)獲取日志
int ret = android_logger_list_read(logger_list, &log_msg);
if (context->printBinary) {
// 根據(jù)上面獲取的文件 fd ,將日志消息寫入文件
printBinary(context, &log_msg);
} else {
processBuffer(context, dev, &log_msg);
}
以 printBinary() 函數(shù)為例:
logcat.cpp # printBinary() :
void printBinary(android_logcat_context_internal* context, struct log_msg* buf) {
size_t size = buf->len();
TEMP_FAILURE_RETRY(write(context->output_fd, buf, size));
}
參考
[ 1 ] Android物語(yǔ):logcat
[ 2 ] android調(diào)試——logcat詳解
[ 3 ] 玩轉(zhuǎn)Android10源碼開發(fā)定制(12)內(nèi)核篇之logcat輸出內(nèi)核日志