Android Dev Summit, October 23-24: two days of technical content, directly from the Android team. Sign-up for livestream updates.

Logcat 命令行工具

Logcat 是一个命令行工具,用于转储系统消息日志,包括设备抛出错误时的堆栈轨迹,以及从您的应用中使用 Log 类写入的消息。

本页面介绍了命令行 Logcat 工具,但在 Android Studio 中,您也可以从 Logcat 窗口查看日志消息。要了解如何在 Android Studio 中查看和过滤日志,请参阅使用 Logcat 写入和查看日志

命令行语法

要通过 adb shell 运行 Logcat,一般用法是:

    [adb] logcat [<option>] ... [<filter-spec>] ...
    

您可以将 logcat 作为 adb 命令运行,也可以直接在模拟器或关联设备的 Shell 提示中运行它。要使用 adb 查看日志输出,请转到您的 SDK platform-tools/ 目录并执行:

    adb logcat
    

要获取 logcat 在线帮助,请启动设备,然后执行:

    adb logcat --help
    

您可以建立与设备的 shell 连接并执行:

    $ adb shell
    # logcat
    

选项

下表介绍了 logcat 的命令行选项。

选项 说明
-b <buffer> 加载可供查看的备用日志缓冲区,例如 eventsradio。默认使用 mainsystemcrash 缓冲区集。请参阅查看备用日志缓冲区
-c, --clear 清除(清空)所选的缓冲区并退出。默认缓冲区集为 mainsystemcrash。要清除所有缓冲区,请使用 -b all -c
-e <expr>, --regex=<expr> 只输出日志消息与 <expr> 匹配的行,其中 <expr> 是一个正则表达式。
-m <count>, --max-count=<count> 输出 <count> 行后退出。这意味着它要与 --regex 配对,但可以独立运行。
--print --regex--max-count 配对,使内容绕过正则表达式过滤器,但仍能够在获得适当数量的匹配时停止。
-d 将日志转储到屏幕并退出。
-f <filename> 将日志消息输出写入 <filename>。默认值为 stdout
-g, --buffer-size 输出指定日志缓冲区的大小并退出。
-n <count> 将轮替日志的数量上限设置为 <count>。默认值为 4。需要 -r 选项。
-r <kbytes> 每输出 <kbytes> 时轮替日志文件。默认值为 16。需要 -f 选项。
-s 相当于过滤器规范 '*:S',用于放在可添加内容的过滤器规范列表之前。
-v <format> 设置日志消息的输出格式。默认格式为 threadtime。有关支持的格式列表,请参阅控制日志输出格式
-D, --dividers 输出各个日志缓冲区之间的分隔线。
-c 清空(清除)整个日志并退出。
-t <count> 仅输出最新的行数。此选项包括 -d 功能。
-t '<time>' 输出自指定时间以来的最新行。此选项包括 -d 功能。要了解如何引用带有嵌入空间的参数,请参阅 -P 选项

adb logcat -t '01-26 20:52:41.820'
-T <count> 输出自指定时间以来的最新行数。此选项不包括 -d 功能
-T '<time>' 输出自指定时间以来的最新行。此选项不包括 -d 功能。要了解如何引用带有嵌入空间的参数,请参阅 -P 选项

adb logcat -t '01-26 20:52:41.820'
-L, -last 在最后一次重新启动之前转储日志。
-B, --binary 以二进制文件形式输出日志。
-S, --statistics 在输出中包含统计信息,以帮助您识别和定位日志垃圾信息发送者。
-G <size> 设置日志环形缓冲区的大小。可以在结尾处添加 KM,以指示单位为千字节或兆字节。
-p, --prune 输出(读取)当前的白名单和黑名单,不采用任何参数,如下所示:

    adb logcat -p
    
-P '<list> ...'
--prune '<list> ...' -P '<white_and_black_list>'
写入(设置)白名单和黑名单,以出于特定目的调整日志记录内容。您可以提供 <white>~<black> 列表条目的混合内容,其中 <white><black> 可以是 UID、UID/PID 或 /PID。在 Logcat 统计信息 (logcat -S) 的指导下,您可以考虑出于各种目的调整白名单和黑名单,例如:
  • 通过 UID 选择使特定日志记录内容具有最长保留期限。
  • 将正在消耗相应资源的人 (UID) 或物 (PID) 列入黑名单,以帮助增加日志跨度,从而更深入地了解正在诊断的问题。

默认情况下,日志记录系统会自动以动态方式将日志统计信息中最严重的违规内容列入黑名单,以便为新的日志消息腾出空间。一旦它用尽启发法,系统便会删除最旧的条目,以便为新消息腾出空间。

添加白名单可保护您的 Android 识别码 (AID),它会变成进程的 AID 和 GID,而不是被声明为违规内容;添加黑名单有助于在相应内容被视为最严重的违规内容之前即释放空间。您可以选择删除内容的程度和频率;也可以关闭删除功能,这样,系统便仅会移除各个日志缓冲区中最旧条目的内容。

引号

adb logcat 不会保留引号,因此指定白名单和黑名单的语法如下所示:


    $ adb logcat -P '"<white_and_blacklist>"'

    or

    adb shell
    $ logcat -P '<white_and_blacklist>'
    

以下示例指定了一个包含 PID 32676 和 UID 675 的白名单和一个包含 PID 32677 和 UID 897 的黑名单。黑名单中的 PID 32677 经过加权处理,以便可以更快删除。


    adb logcat -P '"/32676 675 ~/32677 897"'
    

其他您可以使用的黑名单和白名单命令变体如下所示:


    ~! worst uid blacklist
    ~1000/! worst pid in system (1000)
    
--pid=<pid> ... 仅输出来自给定 PID 的日志。
--wrap 休眠 2 小时或者当缓冲区即将封装时(两者取其先)。通过提供即将封装唤醒来提高轮询的效率。

过滤日志输出

  • 日志消息的标记是一个简短的字符串,指示消息所源自的系统组件(例如,“View”表示视图系统)。
  • 优先级是以下字符值之一(按照从最低到最高优先级的顺序排列):
    • V:详细(最低优先级)
    • D:调试
    • I:信息
    • W:警告
    • E:错误
    • F:严重
    • S:静默(最高优先级,未曾输出过任何内容)

通过运行 Logcat 并观察每个消息的前两列,您可以获取系统中使用的带有优先级的标记列表,格式为 <priority>/<tag>

以下是使用 logcat -v brief output 命令获取的简短 Logcat 输出的示例。它表明消息与优先级“I”和标记“ActivityManager”相关:

    I/ActivityManager(  585): Starting activity: Intent { action=android.intent.action...}
    

要将日志输出降低到可管理的水平,您可以使用过滤器表达式限制日志输出。通过过滤器表达式,您可以向系统表明您感兴趣的标记-优先级组合,系统会针对指定的标记阻止其他消息。

过滤器表达式采用 tag:priority ... 格式,其中 tag 表示您感兴趣的标记,priority 表示可针对该标记报告的最低优先级。不低于指定优先级的标记的消息会写入日志。您可以在一个过滤器表达式中提供任意数量的 tag:priority 规范。一系列规范使用空格分隔。

以下是一个过滤器表达式的示例,该表达式会阻止除标记为“ActivityManager”、优先级不低于“信息”的日志消息以及标记为“MyApp”、优先级不低于“调试”的日志消息以外的所有其他日志消息。

    adb logcat ActivityManager:I MyApp:D *:S
    

上述表达式中最后一个元素 *:S 将所有标记的优先级设为“静默”,从而确保系统仅显示标记为“ActivityManager”和“MyApp”的日志消息。使用 *:S 是确保日志输出受限于您已明确指定的过滤器的绝佳方式,它可以让过滤器充当日志输出的“白名单”。

以下过滤器表达式显示了优先级不低于“警告”的所有标记的所有日志消息:

    adb logcat *:W
    

如果您从开发计算机运行 Logcat(相对于在远程 adb shell 上运行),则也可以通过导出环境变量 ANDROID_LOG_TAGS 的值设置默认过滤器表达式:

    export ANDROID_LOG_TAGS="ActivityManager:I MyApp:D *:S"
    

请注意,如果您从远程 shell 或使用 adb shell logcat 运行 Logcat,则系统不会将 ANDROID_LOG_TAGS 过滤器导出到模拟器/设备实例。

控制日志输出格式

除标记和优先级外,日志消息还包含许多元数据字段。您可以修改消息的输出格式,以便它们显示特定的元数据字段。为此,您可以使用 -v 选项,并指定下列某一受支持的输出格式。

  • brief:显示优先级/标记以及发出消息的进程的 PID。
  • long:显示所有元数据字段,并使用空白行分隔消息。
  • process:仅显示 PID。
  • raw:显示不包含其他元数据字段的原始日志消息。
  • tag:仅显示优先级和标记。
  • thread::旧版格式,显示优先级、PID 以及发出消息的线程的 TID。
  • threadtime(默认值):显示日期、调用时间、优先级、标记、PID 以及发出消息的线程的 TID。
  • time:显示日期、调用时间、优先级、标记以及发出消息的进程的 PID。

启动 Logcat 时,您可以使用 -v 选项指定所需的输出格式:

    [adb] logcat [-v <format>]
    

以下示例显示了如何生成输出格式为 thread 的消息:

    adb logcat -v thread
    

请注意,您只能使用 -v 选项指定一种输出格式,但可以指定任意数量的有意义的修饰符。Logcat 会忽略没有意义的修饰符。

格式修饰符

格式修饰符依据以下一个或多个修饰符的任意组合更改 Logcat 输出。要指定格式修饰符,请使用 -v 选项,如下所示:

    adb logcat -b all -v color -d
    

每个 Android 日志消息都有一个与之相关联的标记和优先级。您可以将任何格式修饰符与以下任一格式选项进行组合:brieflongprocessrawtagthreadthreadtime 以及 time

您可以通过在命令行中输入 logcat -v --help 获取格式修饰符详细信息。

  • color:使用不同的颜色来显示每个优先级。
  • descriptive:显示日志缓冲区事件说明。此修饰符仅影响事件日志缓冲区消息,不会对其他非二进制文件缓冲区产生任何影响。事件说明取自 event-log-tags 数据库。
  • epoch:显示自 1970 年 1 月 1 日以来的时间(以秒为单位)。
  • monotonic:显示自上次启动以来的时间(以 CPU 秒为单位)。
  • printable:确保所有二进制日志记录内容都进行了转义。
  • uid:如果访问控制允许,则显示 UID 或记录的进程的 Android ID。
  • usec:显示精确到微秒的时间。
  • UTC:显示 UTC 时间。
  • year:将年份添加到显示的时间。
  • zone:将本地时区添加到显示的时间。

查看备用日志缓冲区

Android 日志记录系统为日志消息保留了多个环形缓冲区,而且并非所有的日志消息都会发送到默认的环形缓冲区。要查看其他日志消息,您可以使用 -b 选项运行 logcat 命令,以请求查看备用的环形缓冲区。您可以查看下列任意备用缓冲区:

  • radio:查看包含无线装置/电话相关消息的缓冲区。
  • events:查看已经过解释的二进制系统事件缓冲区消息。
  • main:查看主日志缓冲区(默认),不包含系统和崩溃日志消息。
  • system:查看系统日志缓冲区(默认)。
  • crash:查看崩溃日志缓冲区(默认)。
  • all:查看所有缓冲区。
  • default:报告 mainsystemcrash 缓冲区。

以下是 -b 选项的用法:

    [adb] logcat [-b <buffer>]
    

以下示例显示了如何查看包含无线装置和电话相关消息的日志缓冲区。

    adb logcat -b radio
    

此外,您也可以为要输出的所有缓冲区指定多个 -b 标记,如下所示:

    logcat -b main -b radio -b events
    

您可以指定一个 -v 标记,后跟缓冲区逗号分隔列表,例如:

    logcat -v main,radio,events
    

通过代码记录日志

通过 Log 类,您可以在代码中创建日志条目,而这些条目会显示在 logcat 工具中。常用的日志记录方法包括:

例如,使用以下调用:

Kotlin

    Log.i("MyActivity", "MyClass.getView() — get item number $position")
    

Java

    Log.i("MyActivity", "MyClass.getView() — get item number " + position);
    

logcat 输出类似于如下内容:

    I/MyActivity( 1557): MyClass.getView() — get item number 1