我主力用微信输入法,但使用过程中经常莫名其妙切回 ABC。为了把 ABC 从输入源列表里移除,我和 AI 来回排查了一轮,最后确认:重启之后,ABC 没有再出现。
这次最值得记录的,是中途差点把一个猜测当成了原因:看到重启后 ABC 还在,就认定 macOS 把它加回来了,却没有先确认修改是否真正写进了目标文件。
1. 想移除的是输入源
我要做的是从当前用户的输入源列表里去掉 ABC,保留微信输入法。这里涉及的是用户偏好设置,没有必要删除系统输入法文件或关闭 SIP。
正常管理输入源的入口是「系统设置 → 键盘 → 文字输入 → 编辑」。如果只是排查自动切换,也可以先检查「自动切换到文稿的输入法」以及大写锁定键切换输入源的设置。这些选项的作用见 Apple 的输入源设置说明。
这次后续的排查集中在用户配置文件:
~/Library/Preferences/com.apple.HIToolbox.plist
它里面有启用的输入源、输入源历史记录和当前选择等信息。
2. 第一次修改后,ABC 还在
最初我按建议手动编辑 plist,还把修改后的 XML 贴给 AI 检查。那份文本有两个值得注意的问题:
AppleEnabledInputSources后面缺少开头的<array>,却保留了结尾的</array>。如果文件与粘贴文本一致,XML 结构就是无效的;也可能只是复制时漏了一行。AppleInputSourceHistory和AppleCurrentKeyboardLayoutInputSourceID里还有 ABC 的引用。
所以「在编辑器里删掉了一项」并不等于已经获得一份有效、完整且写回成功的配置。
后来我反馈「重启之后 ABC 还在」,AI 随即判断:macOS 在重启时自动恢复了 ABC,需要删除后锁定 plist。
这个判断下早了。 当时没有重启前读取真实文件的结果,也没有前后内容对比。仅凭「重启后还在」,无法区分以下两种情况:
修改没有成功写回目标文件 → 重启后仍然是原配置
修改已写回目标文件 → 后续又被其他进程改回
我当时确认的是手动编辑后重启没有达到目的,并没有验证过「在系统设置里删除成功,重启又恢复」这条过程。
3. 转机:VS Code 打开后的文件名变了
接着我发现,用 VS Code 打开 com.apple.HIToolbox.plist 后,编辑器里显示的却是类似这样的名字:
com.apple.HIToolbox.f65f7d.plist
更关键的是:文件列表里只有原来的那一个文件,但每次双击打开都会看到带后缀的名字;保存、关闭、再打开,之前的修改又没有了。
这让我们开始怀疑,编辑器展示的是转换后的临时副本,或者保存过程没有把修改写回真正的 plist。于是排查重点从「重启时发生了什么」转到了「到底改了哪个文件」。
不过,当时没有继续核查具体扩展、临时文件路径或保存日志,因此不能断言一定是哪一个扩展出了问题,也不能证明原文件每次都一个字节没变。文件名异常是线索,不能单凭它还原整条保存链路。
同样,记录里没有 file 命令的实际输出,不能把「原文件已确认是二进制 plist」当成现场证据。plist 可以是 XML 或二进制格式,实际格式需要检查。
下一步就很明确了:绕开这条编辑器路径,直接读写真实文件,并在重启前检查结果。
4. 最后一轮方案:直接修改、校验,再重启
下面整理最后一轮方案的核心步骤,并补上备份和失败检查。它是这次问题的处理记录,不是 Apple 提供的通用移除接口;不同版本的配置结构可能有差异。先确认微信输入法可用,再关闭系统设置和正在编辑该 plist 的窗口。
4.1 确认路径,先备份
在同一个终端会话中执行:
INPUT_PLIST="$HOME/Library/Preferences/com.apple.HIToolbox.plist"
INPUT_BACKUP="$HOME/Desktop/HIToolbox-$(date +%Y%m%d-%H%M%S).plist.backup"
file "$INPUT_PLIST"
ls -lO "$INPUT_PLIST"
cp "$INPUT_PLIST" "$INPUT_BACKUP"
file 用来看实际格式,ls -lO 用来看文件标志。确认备份成功后再继续。如果之前已经锁过文件,标志中有 uchg,先解锁:
chflags nouchg "$INPUT_PLIST"
4.2 用 Python 直接处理 plist
最后一轮建议还包括在修改前重启当前用户可操作的 cfprefsd:
killall cfprefsd 2>/dev/null
cfprefsd 为 CFPreferences 和 NSUserDefaults 提供偏好设置服务,可用 man cfprefsd 查看说明。缓存或后续写回是需要考虑的因素,但这次没有单独验证它是否造成了回写。上面的命令也不等于获得了一段「系统绝对不会再写配置」的时间窗口。
接下来需要可用的 python3。Python 的 plistlib 能直接读取 XML 和二进制 plist,不需要先在编辑器里转换格式。
python3 - <<'PY'
import plistlib
from pathlib import Path
p = Path.home() / "Library/Preferences/com.apple.HIToolbox.plist"
data = plistlib.loads(p.read_bytes())
if not isinstance(data, dict):
raise SystemExit("配置不是预期的字典结构,停止修改。")
def is_abc(item):
return isinstance(item, dict) and (
item.get("KeyboardLayout Name") == "ABC"
or item.get("InputSource ID") == "com.apple.keylayout.ABC"
)
for key in (
"AppleEnabledInputSources",
"AppleInputSourceHistory",
"AppleSelectedInputSources",
):
if key not in data:
continue
if not isinstance(data[key], list):
raise SystemExit(f"{key} 不是预期的数组,停止修改。")
data[key] = [item for item in data[key] if not is_abc(item)]
for key in (
"AppleCurrentKeyboardLayoutInputSourceID",
"AppleDefaultAsciiInputSource",
):
if data.get(key) == "com.apple.keylayout.ABC":
del data[key]
# 先完成序列化,再打开原文件写入;其他输入源和配置保持原样。
payload = plistlib.dumps(data, fmt=plistlib.FMT_BINARY, sort_keys=False)
p.write_bytes(payload)
if plistlib.loads(p.read_bytes()) != data:
raise SystemExit("写回后的配置与预期不一致,请检查文件。")
print("已清理指定字段中的 ABC 条目,并完成写回校验。")
PY
脚本按内容寻找 ABC,避免手动删除数组下标或 XML 标签。它只删除指定字段中的 ABC 引用,不会把整个输入源列表硬改成微信输入法。原来保留的其他输入源仍然保留;如果配置本身有问题,脚本也不会替你补装或启用微信输入法。
4.3 重启前先检查真实文件
plutil -lint "$INPUT_PLIST"
plutil -p "$INPUT_PLIST"
第一条应报告 OK,第二条用于检查各输入源数组以及当前布局字段。还可以辅助搜索:
plutil -p "$INPUT_PLIST" | grep ABC
defaults read com.apple.HIToolbox | grep ABC
在读取和语法校验都成功的前提下,没有匹配通常表示没有搜到 ABC。不能把管道没有输出直接当成成功:如果前面的命令读取失败,grep 同样可能什么都不显示。磁盘内容和偏好设置读取结果若不一致,也应先查清楚。
4.4 锁定步骤与验证结果要分开看
最后一轮方案还建议在修改、校验之后锁定真实文件:
chflags uchg "$INPUT_PLIST"
ls -lO "$INPUT_PLIST"
uchg 是用户不可更改标志,设置后会阻止文件内容被修改等操作;所有者可以用 nouchg 清除它。它不是「谁都永远改不了」的锁。相关机制可参考 Apple 的文件标志说明。
随后方案建议执行:
killall cfprefsd 2>/dev/null
killall SystemUIServer 2>/dev/null
再重启 Mac,检查登录后的输入源列表。
我最终确认的结果是:这次重启之后没有 ABC 了。 但记录里没有逐条命令的执行日志,也没有只改文件、不锁定的对照实验。因此可以记录这一轮处理成功,不能把成功单独归因于锁文件,更不能证明所有 macOS 环境都必须锁定。
至于最初「使用中自动切回 ABC」的问题,还需要日常使用观察;一次重启后的输入源列表,不能代替长期验证。
5. 锁定之后,怎么修改或恢复
锁定也可能影响正常的输入源设置保存。以后需要增删输入法,先解锁:
chflags nouchg "$HOME/Library/Preferences/com.apple.HIToolbox.plist"
修改后重新检查配置,再决定是否需要锁回去。如果需要恢复备份,在前面同一个终端会话里可以执行:
chflags nouchg "$INPUT_PLIST"
cp "$INPUT_BACKUP" "$INPUT_PLIST"
plutil -lint "$INPUT_PLIST"
killall cfprefsd 2>/dev/null
killall SystemUIServer 2>/dev/null
如果已经换了终端会话,先重新设置这两个路径变量,INPUT_BACKUP 要指向桌面上实际保存的那份备份。恢复后重启,再检查输入源。
6. 这次排查留下的经验
| 观察到的现象 | 能得出的判断 |
|---|---|
| 手动编辑后重启,ABC 仍然存在 | 这轮操作没有达到目的,原因还需要查 |
| 编辑器显示带后缀的文件名,重开后修改消失 | 应优先检查编辑对象和保存是否写回 |
| 直接操作真实路径后,重启不再出现 ABC | 最后一轮处理达到了本次目标 |
| 没有逐项实验和写入日志 | 不能确定临时文件、缓存、锁定各自起了多大作用 |
AI 在前面把「重启后还在」解释成系统恢复,发现文件名异常后,又很容易把「一定没改到原文件」当成另一个确定答案。这两步都跳过了验证。
下次再遇到「配置怎么改都不生效」,我会先确认真实路径,修改后立即读回,再看重启后的状态。把这几个时间点的结果留住,才有依据判断改动究竟在哪一步丢了。
评论讨论