3 步把 MacBook 变成 7×24 远程主机,人在外面随时接管桌面

0 阅读13分钟

先看一张实拍。这是 Amphetamine 的触发器设置界面,把条件设成「接通电源」,Mac 就自动保持清醒,插电生效、拔电恢复,全程不用手。配上远控软件,机器就 7×24 待命,人在外面手机一点,家里的 Mac 和公司的电脑都随时可接管。

Amphetamine 触发器菜单,可按接通电源等条件自动保持清醒

这是我把机器调成 7×24 待命之后的样子。而默认配置下你连过去看到的,多半是一台睡着的 Mac,屏幕黑着,怎么叫都叫不醒,挺崩溃的。

Mac 没人碰就睡,这个省电本能平时是优点,想远程用的时候就是灾难。这篇先把背后的机制讲透,再给出三步完整方案,让任意一台 Mac 变成随时可接入的远程主机。工具就三个,系统自带的 caffeinate,免费的 Amphetamine,加一个远控 App,全程零成本。

赶时间的先抄作业

1. 插上电源
2. nohup caffeinate -s >/dev/null 2>&1 &   # 图形界面党换 Amphetamine 触发器
3. 远控软件设为开机自启,配合系统设置的自动登录

想搞懂每步背后的机制和坑,往后看。

一、先搞清楚 Mac 是怎么睡着的

很多人以为 Mac 的休眠就是设置里的时间一到,屏幕一黑,齐活。

不是,它睡得很讲究。

macOS 内部有一套电源管理系统,所有跟睡眠有关的策略都能用一条命令看到

pmset -g

我把我这台 MacBook 的真实输出截了一段贴出来

displaysleep         180
sleep                1 (sleep prevented by sharingd, powerd)
disksleep            10

注意看 sleep 那一行。我的系统休眠定时器是 1 分钟,按理说这台机器一分钟没人碰就该睡了。但它现在醒着,因为括号里写了,sleep prevented by sharingd, powerd,共享服务和电源管理进程正在阻止它睡。

这就是 macOS 防休眠的核心机制,断言(assertion)。任何进程都可以向系统申请「我要用机器,先别睡」,系统维护一本登记簿,登记簿上有名字,机器就不睡。想翻看这本登记簿,用另一条命令

pmset -g assertions

输出里能看到每个断言属于哪个进程、持有了多久。我写这篇文章的时候,里面就有 WindowServer 因为键盘和触摸板活动而持有的 UserIsActive 断言。

你想想看,放音乐不停、Time Machine 备份到一半、隔空投送正在传文件,这些场景 Mac 都不睡,靠的全是这套机制。

那问题来了,为什么不直接在系统设置里把休眠改成「永不」?

坦白讲,能改,但那是拿笔记本冒险。永不休眠意味着合上盖子塞进包里它也醒着,发热、掉电、烤电池,全来了。我们真正想要的不是「永不睡」,而是「我要用的时候你别睡」,这两件事差得很远。

下面两个主角,caffeinate 和 Amphetamine,干的就是这件事。

二、caffeinate,系统自带、零安装

caffeinate 在 /usr/bin/caffeinate,macOS 自带,不用装任何东西。这个命令 man page 的落款还是 2012 年,算下来它已经默默存在十几年了,说真的,很多人不知道它,挺可惜的。

名字也好懂,caffeinate,摄入咖啡因,让系统清醒。

三种使用形态

形态一,直接跑。

caffeinate

敲下去命令就挂在那,期间系统不会空闲休眠。想解除,Ctrl+C。适合临时挂一会儿的场景,缺点是那个终端窗口得一直开着。

形态二,定时。

caffeinate -t 3600

-t 接秒数,3600 就是保持清醒 1 小时,时间一到断言自动释放,命令自己退出。挂机下载一小时、开一个小时的会,够用了。

形态三,包裹命令,这是它的灵魂。

caffeinate -i make

man page 里自带这个例子。caffeinate 会 fork 一个进程去跑 make,只要 make 还在跑,断言就一直持有,任务跑完,断言自动释放

我在自己机器上实测,包裹命令跑起来时,登记簿里会多出这么一条

pid 6976(caffeinate): PreventUserIdleSystemSleep named: "caffeinate command-line tool"
  Details: caffeinate asserting on behalf of 'sleep' (pid 6974)

on behalf of,代表谁在申请清醒。这就是它比「定时」高级的地方,你不用预估任务要跑多久,任务自己知道。

我日常用得最多的就是这一形态,几个可以直接抄的例子

# 挂机下载,下完自动恢复
caffeinate -i aria2c <下载链接>

# 跑一个长时间的训练脚本
caffeinate -i python train.py

# Homebrew 大版本更新,别中途睡着
caffeinate -i brew upgrade

# 从 Mac ssh 到服务器跑长任务,本地保持清醒防断连
caffeinate -i ssh user@server

参数逐个说清楚

-d   阻止显示器休眠,屏幕保持亮
-i   阻止系统空闲休眠,可以睡屏幕
-m   阻止磁盘休眠
-s   阻止系统休眠,只在接交流电时有效
-u   声明用户是活跃的,屏幕黑了会点亮,默认只持续 5 秒
-t   定时秒数,超时自动释放
-w   等待指定 PID 退出后释放

几个容易踩的点。

-t 和包裹命令一起用是无效的。 man page 写得明白,Timeout value is not used when an utility is invoked。给包裹形态加 -t,系统直接忽略,断言只跟随任务的生命周期,你想限时就选形态二。

-s 只在插电时有效。 电池供电下 -s 不会生效,这是系统的保护,防止电池被干空。

-d 是最费电的选项。 屏幕常亮意味着显示器整晚工作。挂机下载这种活,用 -i 让屏幕睡就行,主机不睡任务就不断。很多人分不清这两个,以为屏幕黑了任务就停了,其实屏幕休眠和系统休眠是两回事,屏幕可以黑着,机器干得热火朝天。

最大的坑,合盖

合盖睡不睡,先看供电,再看断言。

电池供电的 MacBook,合上盖子系统必睡,任何断言都拦不住,这是 Apple 的硬规矩,防止它在包里发热烤电池。这条真没辙。

插着电就是另一回事了。-s 断言在交流电下能拦住合盖休眠,屏幕关了主机照常跑,连外接显示器都不用接

# 插电合盖挂机,主机不睡
caffeinate -s

别光信我,合盖前自己验证一遍。插电跑起 caffeinate -s,合上盖子等几分钟,从手机连一次远控,或者 ssh 进去跑一下 pmset -g assertions 看断言还在不在。不同 macOS 版本对合盖的处理有过差异,信你自己的实测。

官方的合盖运行方案叫蚌壳模式(clamshell mode),要插电加外接显示器。有了 -s 断言,显示器这一步可以省掉。Amphetamine 用户更省事,偏好设置里有一项「显示器关闭时允许系统休眠」,把勾去掉,插电合盖同样保持清醒。

还有一种情况容易被误当成玄学。很多远控软件,TeamViewer、AnyDesk、UU 远程这类,为了保证随时能连上,自己就会持有防休眠断言。我写这篇的时候跑了一下 pmset -g assertions,登记簿里就有 UURemote 挂着的一条

pid 14390(UURemote): PreventUserIdleSystemSleep named: "UURemote Disable Idle System Sleep"

所以有人合盖之后还能远程连上 Mac,不用觉得奇怪,多半是远控软件替他申请了清醒,跟 caffeinate 没什么关系。

纯电池挂机党的正确姿势还是,开着盖子扔那,屏幕自己黑,机器接着干。

三、Amphetamine,图形界面的完全体

命令行党看到上面就够用了。但如果你不想每次都开终端敲命令,或者你的需求是「上班时间插着电就别睡」这种带条件的,就该 Amphetamine 出场了。

Amphetamine 在 Mac App Store,免费,装好之后常驻菜单栏。

App Store 上的 Amphetamine,副标题就是「让你的 Mac 保持清醒」

基本用法没什么学习成本,点菜单栏图标,开始会话。会话可以选时长,30 分钟、1 小时、无限期,也可以选「允许显示器休眠」还是「保持屏幕常亮」,相当于把 caffeinate 的 -i 和 -d 做成了开关。

Amphetamine 菜单栏下拉菜单,点一下就能开始一个无限期会话

真正的价值在触发器 Triggers

触发器是 Amphetamine 和一众「防休眠小工具」拉开差距的地方。与其说它管的是休眠,不如说它是个挂在菜单栏上的条件引擎,条件满足自动开始保持清醒,条件消失自动恢复,全程不用手。

支持的触发条件包括接通电源、连接指定 Wi-Fi 或任意网络、指定 App 正在运行或位于前台、连接外接显示器、连接指定蓝牙设备、特定时间段,这些条件还能组合使用。

说个我自己的配置,插着电源并且连上公司 Wi-Fi 时,自动开始一个无限期、允许屏幕休眠的会话。到家拔了电源,或者切到家里 Wi-Fi,会话自动结束。整个过程我一次都不用点。

再举两个常见玩法。用 Parallels 或 Docker 跑虚拟机的,加一条「Parallels Desktop 或 Docker Desktop 运行时保持清醒」,虚拟机再也不会睡到一半被挂起。做渲染出图的,「Blender 在前台时保持清醒,屏幕常亮」,人离开也不怕。

它和 caffeinate 是亲戚

有意思的地方来了。Amphetamine 底层调的也是断言机制,和 caffeinate 同一套。你开着 Amphetamine 会话时跑一下 pmset -g assertions,登记簿里就有 Amphetamine 的名字,持有 PreventUserIdleSystemSleep 断言,和 caffeinate 出现的方式一模一样。

光看行为还不过瘾,我们把它的二进制拆开验证。先看它链接了哪些系统框架

otool -L /Applications/Amphetamine.app/Contents/MacOS/Amphetamine | grep -i iokit

输出里有 IOKit.framework,电源断言 API 就住在这里面。再用 nm -u 列出它调用的外部函数,三条符号直接摊牌

_IOPMAssertionCreateWithName      创建一个命名断言
_IOPMAssertionRelease             释放断言
_IOPMCopyAssertionsByProcess      枚举全系统断言

创建、释放、枚举,一套齐全。再加一个反向排除,拿 strings 扫整个二进制,caffeinate 这个词出现 0 次。要是它靠拉起 caffeinate 子进程干活,二进制里至少得有这个名字,事实上一个都没有。

所以真实的架构长这样

powerd(系统守护进程,决定睡不睡的裁判)
  ↑ IOPMAssertionCreateWithName / Release(IOKit 公共 API)
  ├── caffeinate    Apple 官方的命令行壳
  ├── Amphetamine   图形界面壳,外加触发器引擎
  └── UURemote、WindowServer、sharingd …  各自直接持断言的进程

顺带一个有意思的细节,IOPMCopyAssertionsByProcess 说明 Amphetamine 还会主动枚举其他进程的断言,大概率是给触发器用的,比如判断是不是已经有别的进程在保持清醒。

这也是我一直觉得这套设计漂亮的地方,Apple 把「申请保持清醒」做成了系统级公共机制,命令行工具、图形界面 App、系统服务,全走同一个入口。caffeinate 是这个机制的命令行皮肤,Amphetamine 是带条件引擎的图形皮肤。

四、3 步把 Mac 变成 7×24 远程主机

前面铺垫了这么多,方案其实就三步,插电、钉住清醒、配上远控。

第一步,插上电源,这是大前提。电池加合盖必睡,不接外接显示器的话没有例外。

第二步,把清醒钉死。这一步有两条路,按口味选一条就行。

命令行版,终端跑一条

nohup caffeinate -s >/dev/null 2>&1 &

nohup 加 & 让它退到后台,关掉终端窗口也继续生效。不嫌麻烦的话,开个终端窗口挂着 caffeinate -s 也行,别按 Ctrl+C 就好。

图形界面版,用 Amphetamine 的触发器,条件设成「接通电源」,动作为自动开始一个无限期、允许显示器休眠的会话,再把偏好设置里「显示器关闭时允许系统休眠」的勾去掉。效果和 caffeinate -s 一致,插电自动生效,拔电自动恢复,连命令都不用敲。

第三步,远控软件设成开机自启,再在系统设置里打开自动登录,保证重启之后不用人到场就能重新待命。

三步做完,这台 Mac 就 7×24 待命了。合上盖子塞到角落,屏幕不亮、机器醒着,任何时间从手机或另一台电脑接入,都是秒连。

所以完整的组合就是两个任选其一,UURemote 加 caffeinate,或者 UURemote 加 Amphetamine。为什么远控软件之外还要自己钉一层防休眠?第二章看过,UURemote 这类软件自己会持有防休眠断言。但那是软件自愿的,它崩溃、你手滑退出、它自动更新重启的那几分钟,断言就没了,偏偏风险集中在这种时刻。自己钉的这一层和它互为备份,坏一个还有一个。

两个注意点。一是散热,合盖跑渲染、训练这类高负载任务时,散热会比开盖差一截,长时间满载建议留条缝。二是重启的边界,自动登录和 FileVault 互斥,开了 FileVault 就得每次人工输密码解锁磁盘,真正无人值守做不到,这是安全和便利的取舍。另外提醒一句,自动登录加合盖塞角落,意味着谁拿到机器谁就能进桌面,机器放在谁够得着的地方,自己心里要有数。过了这关之后,Amphetamine 版本会随登录自动恢复,caffeinate 版本需要重新拉起命令,重度用户可以写个 LaunchAgent 让它开机自启。

五、怎么选

一句话版本,临时救急用 caffeinate,规律性需求用 Amphetamine 触发器,远程主机化两条路都通。

场景用什么
临时挂个下载、跑个脚本caffeinate 包裹命令
固定时长保持清醒,开会演示caffeinate -t 或 Amphetamine 快速会话
条件化自动化,插电、连公司网、虚拟机运行Amphetamine 触发器
7×24 远程主机待命caffeinate -s 后台挂 或 Amphetamine 触发器
完全不想碰命令行Amphetamine
写进脚本或 CI 里caffeinate

我自己的组合是,Amphetamine 触发器管日常,插电加公司 Wi-Fi 自动清醒。临时任务直接 caffeinate 包裹,比如挂个大文件下载。两个都在,五分钟配好,之后零维护。

写在最后

回到开头那张 Amphetamine 触发器菜单截图。远程连不上 Mac,问题从来不在远控软件,在 Mac 自己睡着了。想通了这点,方案就三件小事,插上电,用断言把清醒钉住,让远控软件开机自启。

macOS 把断言机制做成了公共接口,caffeinate 一条命令就能用,Amphetamine 把它包装成全自动的图形界面,远控软件自己也持一份断言。该醒的时候醒,该睡的时候睡,按需来。

最后把命令速查放这,直接抄

# 查看当前休眠策略
pmset -g

# 查看谁在阻止休眠,断言登记簿
pmset -g assertions

# 保持清醒直到 Ctrl+C
caffeinate

# 保持清醒 1 小时
caffeinate -t 3600

# 插电合盖挂机,主机不睡
caffeinate -s

# 退到后台挂着,关终端也生效,远程主机化用
nohup caffeinate -s >/dev/null 2>&1 &

# 任务期间保持清醒,任务结束自动恢复,最常用
caffeinate -i <你的命令>

# 屏幕和系统都不睡,演示场景
caffeinate -di

# 等 PID 1234 退出后恢复
caffeinate -w 1234

希望这篇能让你家的 Mac 随时待命。坑我已经替你踩过了。