拓十年匠心定制 · 商业建站与技术教学双线并行 咨询热线:400-886-1026 service@lmnt.cn
ARTICLE DETAIL

资讯详情

深耕网站建设与运营推广的一线实战洞察。

Stats:macOS 菜单栏系统监视器的安装、配置与源码架构深度解析

Stats:macOS 菜单栏系统监视器的安装、配置与源码架构深度解析
  • 桌面应用
  • 指标监控
  • 可观测性

【免费下载链接】stats

macOS system monitor in your menu bar

项目地址:https://gitcode.com/GitHub_Trending/st/stats
点击查看免费下载

Stats 是一款运行在 macOS 菜单栏中的开源系统监视工具,能够实时展示 CPU、GPU、内存、磁盘、网络、电池、传感器与蓝牙等硬件指标。本文以官方 README.md 为骨架,结合仓库源码,系统讲解它的安装方式、功能模块、常见问题排查与源码级实现原理,帮助读者从"会用"进阶到"看懂"。

项目概览:一个菜单栏里的"系统监视器"

Stats 的核心定位是一句话:macOS system monitor in your menu bar(README.md)。它不提供传统意义上的独立主窗口界面,而是以菜单栏图标、点击后的弹出面板(popup)和可选桌面小组件(widgets)的形式呈现系统状态。

从 Stats/AppDelegate.swift 可以看到,应用启动时会实例化并挂载 10 个监视模块:

var modules: [Module] = [ CPU(), GPU(), RAM(), Disk(), Sensors(), Network(), Battery(), Bluetooth(), Clock(), Remote() ]

每个模块对应一个独立的动态库目标(见 Modules/ 目录),在运行时由宿主 App 统一调度,这种"宿主 + 模块插件"的架构让各功能彼此隔离、可按需启停。README 列出的核心能力包括:

  • CPU 利用率(含每核负载、能效核/性能核/超核集群分组)
  • GPU 利用率
  • 内存使用情况
  • 磁盘利用率
  • 网络使用情况(流量、速率、Wi-Fi 详情)
  • 电池电量与健康度
  • 风扇控制(遗留功能,不维护,见下文"风扇控制"小节)
  • 传感器信息(温度 / 电压 / 功率)
  • 蓝牙设备状态
  • 多时区时钟
  • 远程监视(Remote 模块,SSH/无头模式部署)

环境要求

README 明确了两条硬性前提(README.md):

  • 支持macOS 12 (Monterey) 及更新版本;
  • 不支持 macOS 测试版(Beta),仅支持稳定版本。

从源码看,Sensors模块使用 Objective-C 桥接读取 SMC(Apple 的电源/传感器管理控制器),SMC/目录下存在需要管理员权限安装的eu.exelban.Stats.SMC.Helper特权辅助程序;而 Apple Silicon 与 Intel 的读取路径也不同(如 Modules/CPU/main.swift 中#if arch(x86_64)分支:Intel 上读取 CPU 频率限制,Apple Silicon 上读取频率),因此请务必在受支持的稳定系统版本上使用。

安装方式详解

README 提供了四种安装途径(README.md),其中三种面向普通用户,一种面向远程/无头部署。

手动安装(Manual)

从 Releases 页面下载Stats.dmg,打开后将 App 拖入"应用程序"文件夹即可。这也是最直观的安装方式,适合大多数普通用户。

Homebrew 安装

打开终端执行:

brew install stats

适合习惯用 Homebrew 管理 macOS 软件的开发者,卸载时也只需brew uninstall stats。

无头安装 / SSH 远程部署(Headless)

这是 Stats 最有特色的安装场景:通过 SSH 远程安装 Stats,并把它配置为远程监视代理。执行:

curl -fsSL https://cdn.mac-stats.com/install.sh | bash

脚本会依次完成:安装 App → 启用 Remote 模块 → 打印带授权码的 URL,在任意设备上打开该 URL 并登录你的 System Stats 账号以授权这台机器。授权后,Stats 开始向你的账号持续上报指标,并注册为登录时自动启动、崩溃后自动重启的后台代理。

对应脚本就在仓库的 Kit/scripts/install.sh 中,其参数体系相当完整:

参数作用
-v, --version TAG安装指定 release 标签(默认latest)
-a, --app PATH指定Stats.app的目标位置(默认/Applications/Stats.app)
-c, --control允许远程控制命令
-u, --update允许远程触发更新
-r, --reauth即使已有令牌也强制重新登录
-h, --help显示帮助

脚本内部会处理 Keychain 令牌(eu.exelban.Stats.remote)、注册eu.exelban.Statslaunchd agent 等细节。Remote 模块本身在 Modules/Remote/ 中实现,负责与 System Stats 云端同步机器列表、在线状态、CPU/内存指标快照(如RemoteSnapshot、RemoteCPUModule、RemoteRAMModule等数据结构,见 Modules/Remote/main.swift)。

需要特别注意的限制(README 原话):这台 Mac 必须存在活跃的用户会话(锁屏状态也可以)才能运行 App;在完全无头(无人登录)的机器上,Stats 会在下次登录时才启动。

卸载(Uninstall)

运行 App 自带的卸载脚本(需要管理员权限,因为要移除 SMC 特权辅助程序):

sh /Applications/Stats.app/Contents/Resources/Scripts/uninstall.sh

脚本源码位于 Kit/scripts/uninstall.sh,其清理流程包括:退出 Stats →launchctl bootout卸载 launch agent → 卸载并删除 SMC Helper 的 LaunchDaemon 与特权工具 → 删除 App 本体 → 清理~/Library/Application Support/Stats数据与 Keychain 中的授权令牌。README 同时提示,旧版本(针对更老系统)可从 mac-stats.com 的下载页获取(README.md)。

功能模块与数据采集原理

Stats 的每个模块都由三类"视图"组成:菜单栏 widget(图标区)、popup(点击图标后的弹出面板)与可选的门户/桌面组件,而数据则统一由Reader(读取器)周期性采集。理解 Kit/module/reader.swift 中的Reader<T>基类,就理解了整个数据管线的骨架:

  • 每个 Reader 持有独立的轮询周期interval(默认 1 秒)与回调callbackHandler;
  • 初始化时通过DB.shared.setup(T.self, "\(module)@\(readerName)")在本地 DB 中恢复上一次的采样值;
  • 模块启用时startReaders()启动各 Reader,禁用时lock()+stop()暂停采集(见 Kit/module/module.swift);
  • 存在"可见性感知":只有 popup/预览打开时才需要的 Reader 会进入 sleep 以节省资源(Kit/module/module.swift)。

以 CPU 模块为例,Modules/CPU/main.swift 同时注册了 6 个 Reader:LoadReader(总负载与每核负载)、ProcessReader(进程列表)、TemperatureReader、FrequencyReader、LimitReader(Intel 专属)与AverageLoadReader(1/5/15 分钟平均负载)。采集结果会同步推给 popup、portal、通知、预览和菜单栏各 widget。

模块的"长相"由各自的config.plist决定。以 Modules/CPU/config.plist 为例,它声明了:

  • Name:模块名CPU;
  • State:默认启用(true);
  • Symbol/AlternativeSymbol:菜单栏使用的 SF Symbol(cpu.fill,回退cpu);
  • Widgets:可用 widget 类型及其默认状态、预览值、颜色支持与显示顺序,CPU 模块按序支持label → mini → line_chart → bar_chart → pie_chart → tachometer;
  • Settings.popup/notifications、Preview.available:是否支持弹出面板、通知与预览。

其他模块(如 Modules/Remote/config.plist)结构与之一致,只是默认状态、图标与 widget 集合不同(Remote 默认关闭,使用server.rack图标)。

内存模块的采集则直接调用 Mach 内核接口:host_statistics64(machHostPort, HOST_VM_INFO64, ...)获取active/inactive/speculative/wired/compressed等页统计,并结合vm.swapusage系统调用计算 swap 用量、通过kern.memorystatus_vm_pressure_level判断内存压力等级(normal / warning / critical),见 Modules/RAM/readers.swift。网络模块则借助SystemConfiguration(动态获取主接口)、CoreWLAN(Wi-Fi 协议/加密/信道)与CoreLocation(读取 Wi-Fi 名称所需的定位权限)来获取接口流量与 Wi-Fi 详情,见 Modules/Net/readers.swift。

常见问题排查(FAQ 精讲)

README 的 FAQ 部分集中回答了用户高频问题,以下逐一展开,并附源码佐证。

如何调整菜单栏图标的顺序?

菜单栏图标的排序由 macOS 决定,而非 Stats 本身——安装 Stats 后首次重启,图标顺序可能发生变化。在 macOS Mojave (10.14) 及以上系统,按以下步骤手动调整任意菜单栏图标顺序:

  1. 按住 ⌘(Command 键);
  2. 把图标拖到菜单栏中想要的位置;
  3. 松开 ⌘ 键。

Stats 图标没有出现在菜单栏

macOS 26 新增了一项隐私控制:系统设置 → 菜单栏(Menu Bar)。App 必须在此处被显式允许,才能在菜单栏显示项目。如果 Stats 正在运行、至少有一个模块处于活动状态且至少启用了一个 widget,但菜单栏完全看不到图标,几乎可以断定是这项设置导致的。

解决方法:打开系统设置 → 菜单栏,将Stats开关打开。

桌面小组件不显示数据

由于 App 与小组件通信所依赖的系统进程(chronod)存在高数据负载问题,Stats 侧默认关闭了与小组件的通信。需要用户在 Stats 设置中手动开启macOS widgets选项(README.md)。这与代码中systemWidgetsUpdatesState开关一一对应:只有开启该选项时,CPU 等模块的 reader 回调才会把数据写入SystemWidgetUpdates并同步给桌面组件(见 Modules/CPU/main.swift 与 Modules/CPU/main.swift)。

解决方法:打开Stats 设置,将macOS widgets开关打开。

Wi-Fi 网络名称显示为 Unknown

macOS 要求读取 Wi-Fi 名称时具备定位服务(Location Services)权限。如果 Stats 的定位权限被关闭,网络名称可能直接显示为Unknown,且不会弹出权限提示(README.md)。这正是网络模块在 Modules/Net/readers.swift 中通过isUsableSSID过滤掉空值与<redacted>的原因——系统在未授权时会将 SSID 替换为<redacted>。

解决方法:打开系统设置 → 隐私与安全性 → 定位服务,确认定位服务已开启,并将Stats开关打开,然后退出并重新打开 Stats。

如何降低 Stats 的能耗或 CPU 占用?

Stats 已尽可能追求高效,但周期性读取数据本身并不廉价,而且"每个模块都有自己的开销"。如果想降低能耗,最直接的办法是关闭部分模块。README 明确指出:开销最大的模块是 Sensors(传感器)和 Bluetooth(蓝牙),在某些情况下关闭它们可将 CPU 占用与功耗最多降低约 50%(README.md)。

这一说法与源码架构吻合:传感器模块需要反复读取 SMC 键值(温度/电压/功率),蓝牙模块需要轮询周边蓝牙设备状态,两者的轮询成本天然高于 CPU/内存这类基于内核快照的读取。值得强调的是,50% 是"在某些情况下"的收益,具体效果取决于机器型号与已启用模块数量。

风扇控制(Fan control)

风扇控制目前处于遗留(legacy)模式:不再接收任何更新与修复,也不提供支持。它没有被移除,只是因为它在旧款 Mac 上工作得尚可。项目作者欢迎通过 PR 帮助改进该功能,但自身没有时间和精力继续维护(README.md)。

传感器显示错误的 CPU/GPU 核心数

这是一个高频误解。README 的解释非常关键(README.md):

CPU/GPU 传感器本质上是 CPU/GPU 上的热区(thermal zone),与核心数量或具体核心没有任何关系。例如 CPU 通常分为能效核与性能核两个集群,每个集群包含多个温度传感器,Stats 只是把这些传感器展示出来。因此"CPU Efficient Core 1"并不代表某个能效核的温度,它只是能效核集群内的某一个温度传感器。

此外,每代新 SoC 都会改变传感器键(SMC keys),因此需要花时间确定哪个 SMC 值对应哪个传感器。作者也公开寻求帮助:如果你知道如何在 Apple Silicon 上精确匹配传感器,欢迎联系。

App 崩溃了怎么办?

按以下顺序排查(README.md):

  1. 确认已使用最新版本——大概率已有修复崩溃的版本发布;
  2. 若已是最新版本,查阅已存在的 issue;
  3. 只有当现有 issue 都无法解决你的问题时,才新建 issue。

为什么我的 issue 被直接关闭、没有任何回复?

大概率是因为重复的 issue,且该问题、报告或建议已有答案。请先用"已关闭的 issue"搜索获取答案。

隐私与网络请求:External API

Stats不收集任何遥测或分析数据。它的全部外部请求仅指向以下两个 API(README.md):

  • https://api.mac-stats.com—— 用于更新检查和获取公网 IP 地址;
  • https://api.github.com—— 更新检查的后备(fallback)。

更新检查逻辑与源码中的Updater(github: "exelban/stats", url: "https://api.mac-stats.com/release/latest")对应(见 Stats/AppDelegate.swift),即优先走自有服务器,失败时回退到 GitHub API。公网 IP 的获取特意不用任何第三方服务,而是使用作者自己的服务器。

如果你介意这些请求,有两个选项:

  • 提交一个 PR,让这些功能无需外部服务器即可工作;
  • 用任何网络过滤工具屏蔽上述两个域名(例如你正在使用 Little Snitch 之类工具时很容易做到)。注意:屏蔽后将收不到更新提醒,且网络模块中看不到公网 IP。

开源贡献规范:"Open source, but not open contribution"

Stats 是一个开源但非开放贡献的项目,这一方针在 README 中写得很直白(README.md):

  • 开源:完整源码以 MIT 协议发布,你可以自由阅读、学习、fork 并构建自己的版本;
  • 非开放贡献:项目由单人开发维护,保持稳定与连贯性优先于接受每一个变更——审查外部代码、在不同 Mac 与 macOS 版本上测试、后续维护,往往比从零编写还费时。

因此:未经邀请的 Pull Request 通常不会被接受,且可能未经评审就被关闭。想改动或新增功能,请先开 issue 讨论。例外情况是翻译与语言修复(始终欢迎),以及已经为项目做出重大贡献、实现风格与项目一致的贡献者。

支持项目的最佳方式是:报告 bug、改进翻译、通过 issue 提出想法。

多语言支持

Stats 支持 30+ 种界面语言(README.md),包括简体中文、繁体中文、英语、波兰语、乌克兰语、俄语、土耳其语、韩语、德语、西班牙语、越南语、法语、意大利语、葡萄牙语(巴西/葡萄牙)、挪威语、日语、捷克语、匈牙利语、保加利亚语、罗马尼亚语、荷兰语、克罗地亚语、丹麦语、加泰罗尼亚语、印度尼西亚语、希伯来语、斯洛文尼亚语、希腊语、波斯语、斯洛伐克语、泰语、爱沙尼亚语、印地语、芬兰语、孟加拉语和泰米尔语。

所有语言包都存放在 Stats/Supporting Files/ 下以*.lproj/Localizable.strings形式组织的目录中(如 zh-Hans.lproj),翻译工作由社区成员贡献。如果你愿意,也可以帮助新增语言或改进现有翻译。

许可证

Stats 以 MIT License 协议发布(README.md),允许自由阅读、学习、fork 与二次开发。

  • 桌面应用
  • 指标监控
  • 可观测性

【免费下载链接】stats

macOS system monitor in your menu bar

项目地址:https://gitcode.com/GitHub_Trending/st/stats
点击查看免费下载

相关推荐

上一篇:ctf-wiki 实战指南:利用 QEMU Monitor 的 migrate 命令读取 flag 与实现虚拟化逃逸
下一篇:Windows文件锁定终结者:PowerToys File Locksmith完全指南

创作声明:本文部分内容由AI辅助生成(AIGC),仅供参考

返回列表