logcat
是 android
中的一个命令行工具,可以用于得到程序的log信息。下面介绍 adb logcat
中的详细参数命令以及如何才能高效的打印日志,或者把日志保存到我们指定的位置。
可以输入 adb logcat --help
,查看一下一些简单的数据格式:
adb logcat --help
输出结果:
Usage: logcat [options] [filterspecs]
General options:
-b, --buffer=<buffer> Request alternate ring buffer(s):
main system radio events crash default all
Additionally, 'kernel' for userdebug and eng builds, and
'security' for Device Owner installations.
Multiple -b parameters or comma separated list of buffers are
allowed. Buffers are interleaved.
Default -b main,system,crash,kernel.
-L, --last Dump logs from prior to last reboot from pstore.
-c, --clear Clear (flush) the entire log and exit.
if -f is specified, clear the specified file and its related rotated
log files instead.
if -L is specified, clear pstore log instead.
-d Dump the log and then exit (don't block).
--pid= Only print logs from the given pid.
--wrap Sleep for 2 hours or when buffer about to wrap whichever
comes first. Improves efficiency of polling by providing
an about-to-wrap wakeup.
Formatting:
-v, --format= Sets log print format verb and adverbs, where is one of:
brief help long process raw tag thread threadtime time
Modifying adverbs can be added:
color descriptive epoch monotonic printable uid usec UTC year zone
Multiple -v parameters or comma separated list of format and format
modifiers are allowed.
-D, --dividers Print dividers between each log buffer.
-B, --binary Output the log in binary.
Outfile files:
-f, --file= Log to file instead of stdout.
-r, --rotate-kbytes= Rotate log every kbytes. Requires -f option.
-n, --rotate-count= Sets max number of rotated logs to , default 4.
--id= If the signature for logging to file changes, then clear the
associated files and continue.
Logd control:
These options send a control message to the logd daemon on device, print its return message if
applicable, then exit. They are incompatible with -L, as these attributes do not apply to pstore.
-g, --buffer-size Get the size of the ring buffers within logd.
-G, --buffer-size= Set size of a ring buffer in logd. May suffix with K or M.
This can individually control each buffer' s size with -b.
-S, --statistics Output statistics.
--pid can be used to provide pid specific stats.
-p, --prune Print prune rules. Each rule is specified as UID, UID/PID or /PID. A
'~' prefix indicates that elements matching the rule should be pruned
with higher priority otherwise they're pruned with lower priority. All
other pruning activity is oldest first. Special case ~! represents an
automatic pruning for the noisiest UID as determined by the current
statistics. Special case ~1000/! represents pruning of the worst PID
within AID_SYSTEM when AID_SYSTEM is the noisiest UID.
-P, --prune='<list> ...' Set prune rules, using same format as listed above. Must be quoted.
Filtering:
-s Set default filter to silent. Equivalent to filterspec '*:S'
-e, --regex= Only print lines where the log message matches where is
an ECMAScript regular expression.
-m, --max-count= Quit after printing lines. This is meant to be paired with
--regex, but will work on its own.
--print This option is only applicable when --regex is set and only useful if
--max-count is also provided.
With --print, logcat will print all messages even if they do not
match the regex. Logcat will quit after printing the max-count number
of lines that match the regex.
-t Print only the most recent lines (implies -d).
-t ' <time>' Print the lines since specified time (implies -d).
-T Print only the most recent lines (does not imply -d).
-T ' <time>' Print the lines since specified time (not imply -d).
count is pure numerical, time is 'MM-DD hh:mm:ss.mmm...'
'YYYY-MM-DD hh:mm:ss.mmm...' or 'sssss.mmm...' format.
--uid= Only display log messages from UIDs present in the comma separate list
. No name look-up is performed, so UIDs must be provided as
numeric values. This option is only useful for the ' root', 'log', and
'system' users since only those users can view logs from other users.
filterspecs are a series of
[:priority]
where is a log component tag (or * for all) and priority is:
V Verbose (default for )
D Debug (default for ' *')
I Info
W Warn
E Error
F Fatal
S Silent (suppress all output)
'*' by itself means '*:D' and by itself means :V.
If no ' *' filterspec or -s on command line, all filter defaults to '*:V'.
eg: '*:S <tag>' prints only , ' <tag>:S' suppresses all <tag> log messages.
If not specified on the command line, filterspec is set from ANDROID_LOG_TAGS.
If not specified with -v on command line, format is set from ANDROID_PRINTF_LOG
or defaults to "threadtime"
adb logcat [<option>] ... [<filter-spec>] ...
adb logcat [选项...] [过滤项...],
选项 | 描述 | 举例 |
---|---|---|
-s |
输出指定 tag 的日志,相当于过滤器表达式 *:S |
logcat -s tag |
-f |
设置logcat 内容保存的位置,默认是stdout | logcat -f sdcard/log.txt |
-r |
每输出 时轮替日志文件,默认是16 必须配合 -f | logcat -f sdcard/log.txt -r 1 |
-n |
设置日志输出的最大数目, 需要 -r 参数 | |
-v |
设置日志的输出格式,注意只能设置一项;详见下文 格式化输出 |
logcat -v threadtime |
-D |
输出各个日志缓冲区之间的分隔线 | logcat -D … |
-c |
清除(清空)所选的缓冲区并退出,默认清除 main 、system 和 crash |
logcat -c;logcat -b all -c |
-d |
将日志转储到屏幕并退出 | logcat -d > log.txt |
-e |
输出正则匹配的日志消息 | logcat -e [匹配数据] -m 5 |
-m |
输出 行后退出 | logcat -m 5 |
-t |
仅输出最新的行数,此选项包括 -d 功能 | logcat -t 5 |
-t ' |
输出自指定时间以来的最新行,此选项包括 -d 功能 | logcat -t ‘01-26 20:52:41.820’ |
-g |
获取指定日志缓冲区的大小并退出 | logcat -g |
-G |
设置日志环形缓冲区的大小,可以在结尾处添加 K 或 M |
logcat -G 2M |
-b |
加载可供查看的日志缓冲区,更多可见下文 日志缓冲区 |
logcat -b system |
-B |
以二进制文件形式输出日志 | |
-S |
在输出中包含统计信息,以识别和定位日志垃圾信息发送者 | |
--pid= |
仅输出来自给定 PID 的日志 | logcat --pid=4321 |
Android
日志系统为日志消息保留了多个环形缓冲区,但并非多有的日志消息都会发送到默认的环形缓冲区。这里可以采用 logcat -b
命令查看设备的其他缓冲区:
缓冲区 | 描述 | 举例 |
---|---|---|
radio |
输出通信系统的日志,包含无线装置/电话相关消息 | logcat -b radio |
events |
输出event模块的日志 | logcat -b events |
main |
主日志缓冲区(默认),不包含系统和崩溃日志消息 | logcat -b main |
system |
输出系统日志 | logcat -b system |
crash |
输出崩溃日志 | logcat -b crash |
all |
输出所有缓冲区日志 | logcat -b all |
default |
输出main、system、crash缓冲区日志 | logcat -b default |
使用 -v
命令来修改 log
的输出格式,以显示特定的元数据字段:
格式 | 描述 |
---|---|
brief |
显示优先级、标记以及发出消息的进程的 PID |
long |
显示所有元数据字段,并使用空白行分隔消息 |
process |
仅显示 PID |
raw |
显示不包含其他元数据字段的原始日志消息 |
tag |
仅显示优先级和标记 |
thread |
旧版格式,显示优先级、PID 以及发出消息的线程的 TID |
threadtime |
(默认值)显示日期、调用时间、优先级、标记、PID 以及发出消息的线程的 TID |
time |
显示日期、调用时间、优先级、标记以及发出消息的进程的 PID |
color |
使用不同的颜色来显示每个优先级 |
descriptive |
显示日志缓冲区事件说明。此修饰符仅影响事件日志缓冲区消息,不会对其他非二进制文件缓冲区产生任何影响 |
epoch |
显示自 1970 年 1 月 1 日以来的时间(以秒为单位) |
uid |
如果访问控制允许,则显示 UID 或记录的进程的 Android ID |
usec |
显示精确到微秒的时间 |
UTC |
显示 UTC 时间 |
year |
将年份添加到显示的时间 |
zone |
将本地时区添加到显示的时间 |
对于
-v
选项,如果需要查看线程区别使用logcat -v threadtime
就可以了,其他日志基本也是少用的。
下面列举几种输出格式进行说明。
格式:
<priority>/<tag>(<pid>): <message>
示例:
D/TAG( 1785): Disconnected process message: 10, size: 0
格式:
[ <datetime> <pid>:<tid> <priority>/<tag> ]
示例:
[ 08-28 22:39:39.974 1785: 1832 D/TAG ] Disconnected process message: 10, size: 0
格式:
<priority>(<pid>) <message>
示例:
D( 1785) Disconnected process message: 10, size: 0
格式:
<priority>/<tag>: <message>
示例:
D/TAG: Disconnected process message: 10, size: 0
格式:
<message>
示例:
Disconnected process message: 10, size: 0
格式:
<datetime> <priority>/<tag>(<pid>): <message>
示例:
08-28 22:39:39.974 D/TAG( 1785): Disconnected process message: 10, size: 0
格式:
<datetime> <pid> <tid> <priority> <tag>: <message>
示例:
08-28 22:39:39.974 1785 1832 D TAG: Disconnected process message: 10, size: 0
按日志级别过滤日志:
adb logcat <tag>[:priority]
tag
表示标签;priority
表示输出级别;
日志默认级别是 V
,如果错误日志我们选择 E
就可以,Android
的日志分为如下几个优先级(priority):
选项 | 描述 | 举例 |
---|---|---|
V |
–Verbose(最低优先级) | 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 |
*
可以是某个tag
,如果没有指明,就表示所有。
多数情况下,logcat命令参数都是组合使用。
将进程ID为4321的应用,所有缓冲区日志,按照 threadtime 格式输出到 logcat.log 日志文件中。
adb logcat -b all -v threadtime --pid=4321 > /Users/xxx/logcat.log
将所有缓冲区日志清空。
adb logcat -b all -c
将进程ID为4321的应用,所有缓冲区日志,按照 threadtime 格式输出最新的10行日志(最多10行)。
adb logcat -b all -d -v threadtime --pid=4321 -t 10
private void getLogcat(){
String[] comand = new String[]{"logcat", "-b", "all", "-d", "-v", "threadtime", "--pid=4321", "-t", "10"};
try{
Process exec = Runtime.getRuntime().exec(comand);
BufferedReader reader = new BufferedReader(new InputStreamReader(exec.getInputStream()));
StringBuilder sb = new StringBuilder();
String line;
int i = 0;
while ((line = reader.readLine()) != null) {
sb.append(line).append("\r\n");
}
Log.i("TAG", "logcat content = " + sb.toString());
}catch (Exception ex){
Log.e("TAG", "Exception = " + ex.toString());
}
}
public class LogcatProcesser {
private Process logcatToFileProcess;
/**
* 获取日志输出文件
*/
private String getLogcatFile(){
String path = Environment.getExternalStorageDirectory().getAbsolutePath() + File.separator + "cwlogcat";
File file = new File(path);
if(!file.exists()){
file.mkdirs();
}
return new File(file.getAbsolutePath() + File.separator + "cw_logcat.log").getAbsolutePath();
}
/**
* 开启日志输出到文件
*/
private void startLogcatToFile(){
int pid = android.os.Process.myPid();
String path = getLogcatFile();
try{
String[] cmds = new String[]{"logcat","-b", "all", "-v", "threadtime", "--pid=" + pid, "-f", path};
if(logcatToFileProcess == null) {
// 持续将日志输出到日志文件中
ProcessBuilder processBuilder = new ProcessBuilder(cmds);
// 启动进程并重定向输出
logcatToFileProcess = processBuilder.start();
// 读取进程的错误流,以防止阻塞
readStream(logcatToFileProcess.getErrorStream());
}
}catch (Exception ex){
Log.e("TAG", "Exception = " + ex.toString());
}
}
/**
* 停止日志输出到文件
*/
private void stopLogcatToFile(){
try{
if(logcatToFileProcess == null){
return;
}
logcatToFileProcess.destroy();
logcatToFileProcess = null;
}catch (Exception ex){
Log.e("TAG", "Exception = " + ex.toString());
}
}
/**
* 读取进程的错误流
*/
private void readStream(final java.io.InputStream is) {
new Thread(new Runnable() {
@Override
public void run() {
try {
byte[] buffer = new byte[1024];
while (is.read(buffer) != -1) {
// 读取并忽略输入流中的数据
}
is.close();
} catch (IOException e) {
Log.e("TAG", "Exception = " + ex.toString());
}
}
}).start();
}
}