Skip to Main Content
Mac Chrome ReOpenBack to Top

Mac Chrome ReOpen

9 minutes

问题描述:

Chrome 用 Command+Q 强制关闭程序后,程序在 Dock 栏自己弹了弹又重新弹起来了。

每次都要强制关闭两次以上才能真正把 Chrome 关掉。

Mac 本身的日志功能要多使用,有时能够反应出一定的问题

查看系统的终端报错日志(揪出幕后黑手)

log stream --predicate 'eventMessage CONTAINS[c] "launch"' | grep -i "Chrome"

运行后,终端会进入监听状态。此时你去对 Chrome 执行 Command + Q。 * 观察 Chrome 自动弹起的那一瞬间,终端里跳出来的日志。

2026-06-23 09:21:30.454905+0800 ... loginwindow: [com.apple.loginwindow.logging:TAL] -[PersistentAppsSupport appShouldBeRelaunched:] | entered. checking app: Google Chrome
2026-06-23 09:21:30.454921+0800 ... loginwindow: [com.apple.loginwindow.logging:TAL] -[PersistentAppsSupport saveLogoutPersistentState:finalSnapshot:] |            Adding to relaunchArray: Google Chrome

解释: loginwindow 是 macOS 的登录窗口及会话管理进程。这里的 TAL (Transparent App Lifecycle)PersistentAppsSupport 是 macOS 的“窗口恢复/持久化应用”机制。

翻译成白话: 在 09:21:30 时,macOS 的系统级进程 loginwindow 介入,检测了 Chrome 的状态。它认为 Chrome “应该被重新拉起(appShouldBeRelaunched)”,并直接把它塞进了重启队列(Adding to relaunchArray)里。

随后在 09:21:34 左右,系统底层的 duetexpertd(苹果的智能预测/行为建议服务)和 runningboardd 协同,再次把 Chrome 给捞了起来。

系统级“重新登录时重新打开窗口”的缓存卡死: 即使你没有重启电脑,macOS 误认为你正处于某种退出登录/重启后的恢复流程中。

Chrome 异常退出被系统误判: Chrome 退出时稍微有点慢,导致 loginwindow 以为它“意外崩溃”了,从而触发了系统的自动恢复机制。

方案 A:通过终端强制关闭 Chrome 的“持久化恢复”状态(最直接) – 间歇性有效, 降低出现频率

我们可以利用终端,直接告诉 macOS 系统的 loginwindow 机制:“以后别再记录和恢复 Chrome 的退出了。”

  1. 打开终端 (Terminal)。

  2. 复制并粘贴以下命令,然后按回车:

    Bash

    defaults write com.google.Chrome NSQuitAlwaysKeepsWindows -bool false

    (这行命令会强制关闭 Chrome 的窗口保持与恢复行为)

  3. 接着彻底重置 Chrome 的全局窗口状态缓存,复制并运行:

    Bash

    rm -rf ~/Library/Preferences/com.google.Chrome.plist
  4. 重启一次 Mac 电脑。

方案 B:全面清理 TAL (Transparent App Lifecycle) 缓存 – 无效

在上面给出的日志中,TAL 正在频繁读写缓存。我们去根源上把这部分缓存清空:

  1. 彻底关闭 Chrome。

  2. 在 Finder 中按下 Shift + Command + G,前往:

    Plaintext

    ~/Library/Containers/com.google.Chrome/

    (注意:如果在最新 macOS 中找不到这个确切的 Container 文件夹,可以跳过这步,直接去下一步)

  3. 继续前往:

    Plaintext

    ~/Library/Preferences/ByHost/

    在里面搜索包含 com.google.Chrome 的文件,全部丢进废纸篓。

不做 归因分析, 只解决问题

系统日志 很好用

需求 1:macOS 系统日志功能(Unified Logging)使用要点整理 macOS 自 10.12 引进 统一日志系统 (Unified Logging System) 后,日志不再零散存储于各个文本文件中,而是由 diagnosticd 统一收集并二进制压缩存储。

  1. 核心命令工具:log 实时流监控 (log stream):

要点:它类似于传统 Linux 的 tail -f,但必须配合 –predicate(谓词过滤器)使用,否则海量的系统级 I/O 日志会瞬间刷屏,导致终端卡死。

历史日志检索 (log show):

要点:用于查看过去发生的事情。必须限定时间范围,否则检索极其缓慢。

示例:查看过去 10 分钟内关于 Chrome 的报错:

log show --last 10m --predicate 'eventMessage CONTAINS[c] "Chrome"' --level error
  1. 谓词过滤 (–predicate) 的高级语法 谓词基于 Apple 的 NSPredicate 架构,大小写敏感(除非加 [c] 表示忽略大小写):

process == “loginwindow”:精准匹配进程名。

processImageUUID CONTAINS[c] “Chrome”:匹配进程路径或动态库中包含 Chrome 的行为(对抓取 Helper 应用极有效)。

messageType == error 或 messageType == fault:只看错误或严重故障(fault)。

  1. 日志等级的隐蔽陷阱 macOS 日志分为五个等级:Default、Info、Debug、Error、Fault。

痛点:出于性能和隐私考虑,Info 和 Debug 等级的日志默认是不写入磁盘,也不在实时流中展示的。

解决办法:如果你在调自建脚本(如你的自定义自动化脚本)发现看不到详细日志,需要手动为该进程开启 Debug 级写入:

sudo log config --mode "level:debug" --subsystem com.your.app

需求 2:开源 macOS (Darwin xnu) 代码架构与设计思路 你拉取的仓库实际上是 Darwin(macOS 的开源核心),其内核名为 XNU(X is Not Unix)。XNU 是一个独特的混合内核 (Hybrid Kernel),它融合了 Mach 的灵活性和 BSD 的成熟稳定性。

  1. 核心代码架构(目录结构解密) 在官方开源的 xnu 仓库中,核心架构主要由以下四大板块交织而成:
xnu/
├── mach/               # Mach 微内核层(核心调度与 IPC)
│   ├── kern/           # 线程调度、时钟、任务管理
│   └── vm/             # 虚拟内存管理 (VM Object, Pager)
├── bsd/                # BSD 层(提供 POSIX 标准与上层抽象)
│   ├── kern/           # 进程管理 (PID)、credentials、sysent
│   ├── vfs/            # 虚拟文件系统切换 (Virtual File System)
│   └── netinet/        # TCP/IP 网络协议栈
├── iokit/              # I/O Kit(C++ 驱动框架,负责硬件交互)
│   └── Drivers/        # 磁盘、网络、USB 等基础驱动抽象
├── libkern/            # 内核基础库(C++ 运行时支持、容器类)
└── pexpert/            # 平台专家层(处理不同硬件架构如 ARM64/Intel 的引导初始化)
  1. 核心设计思路 ⚙️ 思路一:微内核与宏内核的“双管齐下”(混合内核) Mach(微内核):只负责最底层、最极致的单一任务——进程间通信 (IPC/Mach Ports)、进程隔离、底层线程调度。Mach 认为万物皆为 “Port”(端口)。

BSD(宏内核):由于微内核频繁进行上下文切换(Context Switch)会导致性能低下,苹果在内核空间里直接嵌套了一个改版的 BSD。BSD 把 Mach 的底层概念包装成 POSIX 标准。

逻辑关系:系统调用进来,上层看到的是 BSD 的 PID(进程 ID),但 BSD 底层其实映射的是 Mach 的 Task。

🔒 思路二:严格的权限与资源断言机制(RunningBoard 的由来) 为什么你会在前面的日志里频繁看到 runningboardd、ttl 和 assertion(断言)?

在 XNU 的设计进化中(特别是引入 iOS 和 Apple Silicon 移动架构后),内核极其看重功耗与生命周期管理。

XNU 引入了 Assertion(资源断言) 机制。一个应用(如 Chrome)在前台时,runningboardd 会向内核申请一个 frontmost 强断言,内核据此分配高优先级 CPU 和能效核心(E-cores/P-cores)。当应用转入后台或准备退出时,断言被 Invalidating(作废),内核会瞬间限制或冻结其 Helper 进程,这也是导致多页面 Chrome 回收假死而被系统强制拉起的底层诱因。

💻 思路三:面向对象的驱动安全(I/O Kit & DriverKit) 传统的 Unix 驱动是用 C 语言写的,一死全死。XNU 独辟蹊径,在内核中实现了一个受限的 C++ 运行时 (libkern)。

设计目的:利用 C++ 的面向对象特性(如依托 OSMetaClass 管理生命周期),让驱动程序对象化。如今苹果正逐步将 I/O Kit 迁移到用户空间(DriverKit),让绝大多数驱动在内核外运行,即使崩溃也不会导致 Mac 蓝屏/紫屏。

通过结合这两点,你会发现:你用 log stream 抓到的每一行状态,其实都是 XNU 内核中 Mach Task、BSD 进程状态以及 RunningBoard 断言在系统层面的具象化表现。