跳转到内容

统一日志:从系统日志里找答案 ​

macOS 的系统日志叫「统一日志」(Unified Logging)。系统和应用的运行记录都写进同一套机制,用 log 命令或「控制台」应用读取。

它的问题不是没有信息,而是信息太多——一分钟几万条是常态。所以这一篇的重点全在筛选上。不会筛选,打开日志只会被淹没;会筛选,很多「毫无线索」的故障能直接看到原因。

开始之前 ​

本文命令全部只读。需要能在终端执行命令。日志内容可能包含文件路径、网址等信息,贴到网上求助前先自己看一遍,去掉不该公开的部分。

两个基本动作 ​

看过去的日志用 log show:

sh
log show --last 5m

--last 5m 表示最近 5 分钟(m 分钟、h 小时、d 天)。直接这么跑会刷出海量内容,先见识一次也好,知道为什么必须加筛选。

看正在发生的用 log stream:

sh
log stream

它持续输出新产生的日志,按 Control-C 停止。排查「点一下就出错」这类问题时最好用:先跑 log stream,再去触发那个操作,报错会实时出现。

谓词:只看想看的 ​

--predicate 接收一个筛选表达式,语法是 Apple 的 NSPredicate 格式。常用字段只有几个:

字段含义
process产生日志的进程名
subsystem子系统标识,通常是反向域名如 com.apple.network
category子系统内部的分类
eventMessage日志正文

按进程筛选是最常用的:

sh
log show --last 10m --predicate 'process == "Safari"'

注意引号的用法:整个谓词用单引号包住,里面的字符串值用双引号。写反了 shell 会先做变量展开,结果往往莫名其妙。

按内容搜索:

sh
log show --last 1h --predicate 'eventMessage CONTAINS "error"'

CONTAINS 是包含匹配。想忽略大小写就写 CONTAINS[c],[c] 是大小写不敏感修饰符。

组合条件用 AND 和 OR:

sh
log show --last 30m --predicate 'process == "backupd" AND eventMessage CONTAINS[c] "fail"'

这条实际可用——backupd 是时间机器的后台进程,这样能查出最近一次备份失败的原因,比在界面上看「备份失败」有用得多。

默认看不到全部级别 ​

日志有四个级别:default、info、debug、error/fault。log show 默认只显示 default 及以上,info 和 debug 被隐藏。

sh
log show --last 5m --info --debug --predicate 'process == "cfprefsd"'

--info 和 --debug 分别把这两级加进来。排查时如果觉得「日志里什么都没有」,多半是漏了这两个开关。

代价是输出量显著增加,所以这两个开关应当和精确的谓词一起用。

log stream 那边对应的是 --level:

sh
log stream --level debug --predicate 'subsystem == "com.apple.TimeMachine"'

让输出好读一点 ​

sh
log show --last 10m --predicate 'process == "Dock"' --style compact

--style 控制格式:default 最详细,compact 每条一行较易扫读,syslog 是传统格式,json 和 ndjson 便于程序处理。

排查时先用 compact 快速扫,锁定时间点后再去掉它看完整信息。

为什么很多内容显示成 private ​

你会频繁看到 <private>。这是有意的隐私保护:开发者在写日志时可以标记哪些内容属于敏感数据,系统在输出时把它们隐去。

这不是故障,也不该想办法绕过——网上那些让你改系统配置来显示全部内容的做法,等于在整机范围内长期打开一个隐私缺口,而你通常只是想看一行内容。

实际可行的替代:换个角度筛选。看不到具体文件名时,用时间点和进程名对照你当时的操作,往往足以判断问题所在。

把日志存下来给别人看 ​

需要提交给开发者时:

sh
log collect --last 1h --output ~/Desktop/问题日志.logarchive

log collect 把日志打包成 .logarchive,--last 限定时间范围,--output 指定保存位置。生成的文件可以用「控制台」打开,也可以用 log show --archive 读取:

sh
log show --archive ~/Desktop/问题日志.logarchive --predicate 'process == "Safari"'

发送之前务必确认内容。 日志归档里包含大量系统活动记录,可能有文件路径、设备名、网络地址。只发给你确实信任的接收方,并且只截取需要的时间范围——--last 1h 比整包合适得多。

控制台应用 ​

图形界面的「控制台」(应用程序 → 实用工具)提供同样的数据,好处是能实时滚动、点选过滤,缺点是无法保存复杂的筛选条件,也不方便把结果贴进笔记。

建议:临时观察用控制台,需要复用或分享的筛选写成 log 命令。

检查结果 ​

sh
log show --last 2m --style compact | head -20

能输出内容,说明日志系统正常。head -20 只取前 20 行,避免刷屏。

sh
log show --last 1d --predicate 'process == "backupd"' --style compact | tail -20

用过时间机器的话,这里能看到最近的备份活动。tail -20 取最后 20 行,也就是最新的几条。

动手练习 ​

制造一次可控的故障,然后在日志里找到它:

  1. 开一个终端窗口执行 log stream --style compact --predicate 'eventMessage CONTAINS[c] "quarantine"'。
  2. 另开一个窗口,用浏览器下载任意一个小文件。
  3. 回到第一个窗口,观察是否出现相关记录,按 Control-C 停止。
  4. 换一个练习:执行 log show --last 1h --predicate 'process == "sudo"' --style compact,找出你今天用过 sudo 的记录。
  5. 把第 4 步的谓词改成一个不存在的进程名,确认输出为空——空结果和「筛选写错了」长得一样,这一步是为了让你亲眼确认两者的区别。

成功标准是第 4 步:你能从整机日志里精确捞出某一类事件。养成「先想清楚要筛什么,再执行」的习惯之后,统一日志会从噪音变成最直接的排查工具。更系统的排查思路见故障排查总览。

返回系统内部