無標題文檔

解决 macOS 下 iPhone 镜像反复连接失败的问题

Screenshots

最近将 Mac 升级到 macOS Beta 以后,iPhone 镜像突然不能用了。Mac 明明可以找到旁边的 iPhone,但每次打开 iPhone Mirroring,最后都只会得到一个 Unable to Connect to iPhone,点 Try Again 也没什么用。

该检查的其实都检查过了:两边是同一个 Apple 账户,Wi-Fi、蓝牙和接力也都开着,手机就在旁边并且处于锁屏状态,VPN、个人热点、AirPlay 和随航也没有占用。同时,还有个比较奇怪的地方,就是「iPhone 镜像 → 设置」里的「撤销 iPhone 访问权限」是灰色的。看起来系统认为没有已经授权的手机,但它又确实能发现这台手机。

最后折腾下来,问题出在 replicatord 留下的配对状态。这里记录下排查和修复过程,免得下次再碰到又从 Wi-Fi 开始查一遍。下面,简单记录下排查和解决的过程。

先看日志

首先确认几个相关服务是否还活着:

pgrep -alf 'iPhone Mirroring|replicatord|sharingd|rapportd'

然后打开 iPhone 镜像,点一次 Try Again,再查看最近五分钟的日志:

log show --style compact --last 5m --info --debug \
    --predicate '(process == "iPhone Mirroring" OR process == "replicatord" OR process == "rapportd" OR subsystem CONTAINS[c] "Replicator" OR subsystem CONTAINS[c] "ScreenContinuity")' \
    | grep -Ei 'noCompatiblePhone|pairing|paired|unsupported|error|fail|eligible|device'

这里比较关键的几行,脱敏以后大概是这样:

Checking if Mac is supported
Checking if Mac is eligible
Checking if iCloud is in a healthy state
Checking if WiFi is powered on
Checking if continuity feature is enabled
Checking if Replicator has a device paired
Fetched 1 devices
Got devices: [...; pairing; phone; ...]
Tearing down the session due to: noCompatiblePhone

与此同时,rapportd 已经能看到下面这些状态:

PairedBT, PairedSys, WiFiP2P, MyiCloud, AcLv CoverClosed

也就是说蓝牙发现、同一 iCloud、Wi-Fi P2P 和手机锁屏其实都没有问题。真正可疑的是 replicatord 找到了设备,但它的状态一直停在 pairing,随后 iPhone 镜像将其当成了 noCompatiblePhone

先试试简单的办法

在动数据库以前,先重启了当前用户的几个连续互通服务:

killall -TERM sharingd rapportd 2>/dev/null
open -a 'iPhone Mirroring'

这个操作不会删除配对信息。如果重新打开以后还是失败,可以再去应用设置里试试「撤销 iPhone 访问权限」。按钮能点的话,直接用系统提供的方式重新配对最好。

但我这里的按钮是灰色的,所以只能手动清掉这条半死不活的记录。

重建 Replicator 配对数据库

replicatord 的当前用户数据库通常在这里:

~/Library/Group Containers/group.com.apple.replicatord/replicatord/

先退出 iPhone 镜像,并且给数据库做个备份:

osascript -e 'tell application "iPhone Mirroring" to quit'

BACKUP="$HOME/Desktop/replicatord-backup-$(date +%Y%m%d-%H%M%S)"
STATE="$HOME/Library/Group Containers/group.com.apple.replicatord/replicatord"
mkdir -p "$BACKUP"

然后停掉当前用户的 replicatord

launchctl bootout "gui/$(id -u)/com.apple.replicatord"

这里没有删除数据库,只是把 SQLite 文件和对应的 WAL 文件挪到刚才的备份目录:

for file in replicatord.sql replicatord.sql-wal replicatord.sql-shm; do
    [ ! -e "$STATE/$file" ] || mv "$STATE/$file" "$BACKUP/$file"
done

最后重新拉起服务:

launchctl bootstrap "gui/$(id -u)" \
    /System/Library/LaunchAgents/com.apple.replicatord.plist

killall -TERM sharingd rapportd 2>/dev/null
open -a 'iPhone Mirroring'

重新打开以后,系统会生成新的数据库,并且再次建立镜像关系。按界面提示解锁或确认 iPhone,完成以后再把手机锁上即可。

验证和回滚

连接成功后,可以用 SQLite 看一下新的关系状态:

sqlite3 \
    "$HOME/Library/Group Containers/group.com.apple.replicatord/replicatord/replicatord.sql" \
    'SELECT RemoteDeviceType, State, count(*) FROM PairingRelationship GROUP BY RemoteDeviceType, State;'

这里重建前设备一直是 pairing,重建后数据库中的关系进入了 State = 2,日志也开始建立 AVConference 音视频流。退出应用、锁定手机再打开一次,镜像仍然可以正常连接,最近的日志里也没有再出现 noCompatiblePhone

如果重建以后反而有其他问题,可以先退出应用并停掉服务,再把备份放回去:

osascript -e 'tell application "iPhone Mirroring" to quit'
launchctl bootout "gui/$(id -u)/com.apple.replicatord"
mv "$BACKUP"/replicatord.sql* "$STATE"/
launchctl bootstrap "gui/$(id -u)" \
    /System/Library/LaunchAgents/com.apple.replicatord.plist

确认稳定使用一段时间以后,桌面上的备份目录就可以删掉了。个人更建议直接去 Finder 里删除,至少比复制一条带变量的 rm -rf 安心些。

总结和思考

这次刚好是 macOS Beta 搭配上一代稳定版 iOS,所以最开始也怀疑是两边的协议版本不兼容。毕竟 iPhone 镜像牵涉到蓝牙近距发现、Wi-Fi P2P、iCloud 身份以及 RapportSharingReplicator 等一串私有协议,系统升级以后旧配对失效并不奇怪。

但就这次的结果来看,清掉 Mac 本地的单条配对数据库以后马上恢复,说明直接原因还是 replicatord 的状态不一致,跨版本更像是触发问题的诱因。

如果重新配对以后仍然失败,同时日志里出现 unsupported、版本协商失败,或者根本找不到可配对设备,那才更像是真正的兼容性问题。这种情况下还是先升级到更新的 macOS Beta 或正式版比较合适,没必要为了验证一个猜测,就把主力 iPhone 也升级到测试版。

在 Claude Code 中配置使用 Ring 1T 模型

最近收到通知,Gmail 因为“安全的原因”要逐步停止支持 POP3 收取第三方邮件。这对我来说是个小麻烦,因为学校的邮箱和 Gmail 之间的同步需要找替代方案。

想想其实用第三方服务还是不太靠谱,加上事情本身也不大复杂。索性利用假期的时间用 Rust 写了个小工具 mail-forwarder 来自动转发。在这个过程中,我开始大量使用 Claude Code,这个体验还真不错。总体来说,用 Claude Code 写代码的流畅度确实很不错,但有几个点不太满意:

  1. 只能用 Anthropic 自家的模型,没得选
  2. 用官方的有点不划算,有点小贵(当然这也有可能是我自己的问题)
  3. 国内无法直接访问只能挂梯子,导致访问速度不理想

后来发现 Claude Code 的接口其实很简洁,通过改几个环境变量就能接入其他模型提供商。经过一番调研,我选了 ZenMux 这个平台,主要是因为它国内访问快,支持一堆不同的模型,接口文档也写得清楚,总体来说可以作为 OpenRouter 的一个不错的替代方案。

先说结论吧,暂时在 ZenMux 上提供众多模型中,最后挑了 Ring 1T 作为替代方案。主要是它在推理和代码生成上表现确实不错,价格也比较合理,性价比不错。

这篇文章就是把这个折腾过程整理一下,看看能不能帮到有类似需求的人。

开始配置

1. 安装 Claude Code

这个其实不用多说,直接用官方安装脚本最简单,复制粘贴下:

curl -fsSL https://claude.ai/install.sh | bash

装好了可以验证一下:

claude doctor

顺便说一句,我这里碰到了个坑,安装完成后 claude doctor 报错说找不到 ~/.claude/settings.json,后来发现是因为之前用过其他服务的配置文件有冲突,删除掉那个文件重新启动 Claude 就好了。

2. 获取 ZenMux API 密钥

ZenMux 官网 注册个账号。新用户有试用额度,可以拿来直接试用(先说明,这个链接带 AFF 码,注册后你和我都能拿到奖励)。

3. 配置环境变量

这是关键一步。打开你的 Shell 配置文件:

# 如果用 zsh(macOS 默认)
nano ~/.zshrc

# 如果用 bash
nano ~/.bashrc

在文件末尾加上这些:

# ZenMux + Claude Code 配置
export ANTHROPIC_BASE_URL="https://zenmux.ai/api/anthropic"
export ANTHROPIC_AUTH_TOKEN="sk-ss-v1-xxx"  # 改成你的 API 密钥
export CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC="1"
export API_TIMEOUT_MS="30000000"
export ANTHROPIC_DEFAULT_SONNET_MODEL="inclusionai/ring-1t"

然后重新加载配置即可。

4. 启动试试

打开新终端,进到你的项目目录,输入:

cd /path/to/your/project
claude

第一次启动会要求登录授权,直接用环境变量里配置的 API 密钥就行。

常用的几个命令

启动后就可以开始用了。常见的命令:

  • /model —— 查看当前模型,或者切换模型
  • /status —— 看看连接状态和配置是否正确
  • /help —— 显示所有支持的命令
  • /clear —— 清空对话历史

最简单的用法就是直接问代码问题,像:

请帮我优化这个函数的性能
分析一下这个 bug 的原因
给这个类写 unit tests

最后,该说说下实际用下来的感受了,纯个人体验供参考:

推理能力确实不错

Ring 1T 在理解复杂逻辑上表现还是挺好的。我用它给 mail-forwarder 的某些关键部分做代码审查,它能指出逻辑漏洞、性能瓶颈,建议也都比较中肯。对比之前直接用 Claude,差别说实话不是特别明显,但至少 Ring 1T 的性价比更高。

国内访问速度提升明显

这个是我最满意的一点。之前直接用官方 API,有时候响应会卡顿。现在走 ZenMux 的节点,国内访问流畅多了,尤其是半夜用的时候。网络稳定性也更好。

Token 消耗需要关注

复杂的任务确实会吃很多 token。比如我让它分析整个项目结构、写详细的测试用例这种,token 消耗就比较明显。我测试了下相对 Gemini 这种更大模型,Ring 1T 的消耗还是比较合理的,但是推理复杂度高的时候,还是需要注意一下。

偶尔有延迟

处理特别长的文本,或者特别复杂的推理任务,有时候响应会慢一点。不过这个通常不是 Ring 1T 的问题,主要可能是网络或者任务本身就很重。总体来说可以接受。

国际化的问题

可能 Ring 1T 是国内模型的缘故,在处理一些特定的中文语境或者专业术语时,偶尔会有理解偏差。同时其模型偏好在没有特别指定语言的时候,也可能倾向于中文输出,这时候需要在提示词里明确一下语言要求。

使用场景

好了综述所述,总结下我现在最常用的是这几个:

  1. 快速代码审查方面,丢段代码给它看,通常能发现我没想到的问题。没有心智负担,因为价格便宜很多;
  2. 调试复杂问题:描述现象,让它帮忙分析原因,成功率还是挺高的;
  3. 帮忙写测试和文档,特别省时间,质量也还不错,尤其如果是中文环境下的项目,Ring 1T 的表现会更好一些,而且避免了 Anthropic 非要用英文输出以及生成冗余文档的情况。

总的来说,这个配置折腾一次就行了。目前用下来感觉比直接用官方 Claude 爽,成本更低,国内访问也更稳定(当然也有可能目前只是针对 mail-forwarder 这种小需求的情况)。

这个折腾总体来说其实挺值得的,花杯星巴克的钱订阅 ZenMux,用 Ring 1T 的推理能力,国内访问也快,成本比官方便宜得多。如果你也在用 Claude Code,又对国内访问或者模型选择不太满意,不妨考虑试试这个方案。配置其实很简单,5 分钟就搞定,值得的。

感谢 Drone CI,同时迁移到了 Gitea Actions

自建使用 Git 仓库其实很久了,当时的原因很简单就是因为 Github 的私有仓库不是免费的。虽然期间也续费过 Github 会员好多年,但是毕竟还是自建来得吃香,就这样子兜兜转转用下来这个 Gitea 的实例看了下日期其实比我手头上使用的任何数码硬件设备都要久了。

当时的 Gitea 项目还不是很成熟,甚至连 CI 模块都没有需要搭配第三方 CI 平台来使用。而我自己个人也不喜欢 Gitlab 那么臃肿的架构设计,于是 Gitea 和 Drone CI 的搭配就一直这样子沿用了下来。

近期在整理 Git 仓库和代码的时候,顺手又将 Gitea 升级了下,发现已经是 1.21 版本了,还自带了 Gitea Actions。于是从精简系统的角度上考虑,是不是需要将其替换掉 Drone CI?从我调研以及使用的过程看来,答案是肯定的。

那么 Drone CI 有什么不足的地方呢,主要的问题有以下几点:

首先,原本的 Drone CI 是开源项目但是有完整的商业目标,因此在被 Harness 收购了以后开源的版本更新其实并不及时,这就导致界面非常的简陋,同时也和 Getea 的界面相差甚远。其次,Drone CI 是作为 Gitea 的应用来注册的,然后通过 WebHook 的方式来相互通信,这就导致会有不同的问题发生,例如权限、网络延迟以及缓存等等的问题。还有一点就是,随着研发团队人员的增加,很多时候权限的粒度需要精确的控制,Drone CI 至今都无法完成从全局(Global)、组(Organization)、项目(Project)程度的权限控制。

然后替换为 Gitea Actions 以后又将会获得什么好处呢?

首先就是完整的产品体验,至少界面以及权限这块是保持一致的。然后,Gitea Actions 和 Github Actions 保持了配置方面的兼容性,这让我原本需要分别配置两套 CI 的 yaml 一下子工作量就减轻了不少,同时 Github Actions 丰富的生态也可以在 Gitea Actions 上得以延续。

当然,目前还有一点需要注意的是,Gitea 官网上说明 Gitea Actions 还在开发阶段功能方面不是很稳定,可能随时需要更新。所以切换到 Gitea Actions 以后,那么需要随时关注更新版本(但至少从我目前几个项目的配置看来,没有发现大的问题)。

总体来说,Drone CI 任然还是非常优秀的 CI 平台,只是随时时间的推移可能目前来说已经不适合我而已。对于 Drone CI 的情感还是非常的感激的,毕竟陪伴了我很多日夜的开发之路。

我的照片

您好!我叫「明城」,八零后、码农、宁波佬,现居杭州。除了这里,欢迎您通过 GitHubTwitterInstagram 了解我的更多动态。

本博客原名 Gracecode.com 、现更名 「無標題文檔」「精于心、简于形」以此践行极简、务实的理念。 在工作之外的个人生活方面,我崇尚简单、追求平淡,偶尔也带着一些可能不被所有人理解的幽默感。

同时为避免争议和麻烦,在此郑重声明:本站所有内容为非 AI 生成,所有观点及立场均仅代表我个人,不代表任何我所就职或关联的公司与组织。

如果您想联系我,可以发我邮件 `echo bWluZ2NoZW5nQG91dGxvb2suY29tCg== | base64 -d`

分类

搜索

文章

Image