从 ShadowsocksX 客户端配置文件说到 OS X user default plist

起因:本人在 Mac 上使用的 shadowsocksX 客户端,虽然有备注功能,但是服务器一多就经常眼花看不清,因此我就想过能不能调整一下服务器在列表中的排列顺序(吐槽一下 surge 的配置组功能还是挺好的,可惜 ss 已经停止维护了),然后尴尬地发现在这个客户端 GUI 上不具有调整服务器配置顺序的功能,但是想了想 Windows 的 dotNET 客户端都有 gui-config.json 这样的配置文件保存在 EXE 同路径下,大概 shadowsocksX 应该也有类似的文件吧?

于是乎我跑去 Github 翻了半天源码想找配置文件保存路径并没有发现,感觉是调的系统的接口(实际上是在 ShadowsocksX/Supporting files/ProfileManager.m 这个文件是配置文件相关源码,但是我既没写过 OC 也没用过 cocoa 框架并不能看懂是调的什么API/怎么存的这 TM 就非常尴尬了

于是又去搜了一下关于 Mac 客户端配置文件存储的问题,于是乎找到了这个 issue

QQ20160402-1@2x

这 TM 就更尴尬了,找了半天作者说我们没有配置文件。

1f178a82b9014a90a12bde0ea9773912b31bee68

但是你们总得有个地方存配置吧?

于是乎从这个 issue获得提示,找到了 ~/Library/Preferences/clowwindy.ShadowsocksX.plist

看了 default read ~/Library/Preferences/clowwindy.ShadowsocksX.plist 了一下确实如 issue 里所说,有个字段不知道是个什么玩意(废话这是二进制格式的 plist 直接读取当然会出问题)

这里需要首先提一下 Apple 的 plist 文件到底是个什么玩意,这个问题还是坑了我挺久的。

OS XCocoaNeXTSTEPGNUstep编程框架中,属性列表(Property List)文件是一种用来存储序列化后的对象的文件。属性列表文件的文件扩展名.plist,因此通常被称为plist文件。Plist文件通常用于储存用户设置,也可以用于存储捆绑的信息。——Wikipedia

简单的说就是 Apple 使用的特殊的配置文件格式,在 Mac OS X 中,plist 被定义为使用 xml 标准的格式(实际上用过越狱的 iOS 的大概也看过这种 plist 文件,iOS 中也使用这个格式进行 APP 的配置),其开头有这样的声明:

plist 可以包含<string>(字符串)、<real>, <integer>(数值)、<true />, or <false />(布尔值)、<date>(日期字符串)、<data>(被 base64编码过的任意数据)、<array>(数组)、<dict>(字典,交替包含<key>标签和plist元素标签)。

但是非常操蛋的问题是什么呢,xml 是一种低效率的文件格式,虽然增加了可读性,但是需要的存储空间增加了,因此 Apple 在 OS X 10.2 中引入了 bpilist 也就是二进制格式的 plist,并从10.4之后成为默认配置文件存储格式。

ShadowsocksX 客户端使用的这个 plist 就是 bplist,实际上也是 OS X 的 user default 系统中的一部分,

OS X applications and other programs use the defaults system to record user preferences and other
information that must be maintained when the applications aren’t running (such as default font for new
documents, or the position of an Info panel). Much of this information is accessible through an appli-cation’s application’s
cation’s Preferences panel, but some of it isn’t, such as the position of the Info panel. You can
access this information with defaults——OS X man pages

简单的说是类似 Windows 注册表一样的东西,但是这个不是像注册表是集中管理的,直接使用编辑器打开的话,就看各自设定了,Xcode 打开的时候会自动调用 plist 编辑器(这个时候 data 字段里被 base64 转义过的内容会以16进制形式出现),空格预览和 TextWranger 打开的时候会转成 xml,vim 和 sublime 则是直接以二进制形式打开(因此会有识别错误的字符,但是 data 字段里的内容会直接呈现出来)


 

PS.这个 plist 修改前请务必备份 ,错误的配置文件会使客户端无法启动且删除客户端重新安装无效,使用 defaults delete clowwindy.ShadowsocksX可以使客户端重新生成新的空plist,但是也会丢失现有的所有服务器信息


 

实际上 OS X 提供了 plutil 这个工具可以对各种 plist 文件进行转换和拼写检查(实际上 default read 命令就是调用了 plutil -lint)。

那么我们需要调整 ShadowsocksX 中的服务器列表,可以先把原有配置文件转成可读的 xml:

在<key>config</key>字段下的<data>字段就是保存了现有服务器信息的字段,整个复制出来,base64解码(OS X 的 base64 工具在从 stdin 读入数据的时候有长度限制十分无语,建议先保存到文件再读入):

-D 表示解码,-i 表示读入的文件路径,-o – 表示输出解码结果到 stdout,也可以保存到新文件方便编辑。

PS.顺便一提这个 json 和 Windows 客户端的 gui-config.json 的格式完全不同,并不能优雅地从 win 导入配置,我也不知道作者是怎么设计的。

修改后 base64 编码填回 xml(不加 -D 选项即是编码)

如果此时 plist 格式错误,plutil 会中止操作,使用 plutil -p可以对文件进行拼写检查, 重新载入 plist:

重新打开 ShadowsocksX 客户端,就能看到新配置已经载入。


PS.

QQ20160402-2@2x

强迫症表示排列整齐了我巨爽

4条评论


  1. 不错不错,多谢楼主,看了这篇后搞定了

    回复

发表评论

电子邮件地址不会被公开。 必填项已用*标注