menu
OSX 10.11 无法使用 EasyConnect 问题的排查与解决

前言

在苹果 6 月的开发者大会的洗脑下,小雨荣幸成为一名 OSX10.11 小白鼠。当时柏涛君信誓旦旦跟我说,如丝般顺滑流畅,我还真 TM 信了。随后便遇到了各种问题,什么 JDK6 无法安装,IDEA 各种大姨妈,Fantastical 无法使用。然而,最坑的问题是,我无法使用公司 VPN,无法使用公司 VPN,无法使用公司 VPN。因为很重要,所以要说三遍。

才开始我以为和以前一样,是因为系统升级,需要重新安装,于是我重新下载安装客户端,没用。后面便有了各种折腾大法,什么浏览器安全等级大法,插件安全策略法,上网寻找最新的安装包更新法,无解……

本着基本平常都在公司加班,回家也有舍友的电脑的想法,我暂时放弃了治疗。勘弁して!~~本想着因为用的是开发版,到了正式版应该能解决,然而,上周更新的 GM 版本(等价于正式版)让我彻底放弃,VPN 君,就是连不上啊。QAQ

但是中秋和国庆,我好死不死地准备请假三天连休那么个十几天,しまった!我突然想起来,到时候回了家后家里可就只有我一台电脑,到时候出了什么事,那还得了!于是,我又一次踏上了解决 VPN 问题的不归路……

排查

首先分析系统日志,一下子便看到如下内容:

15/9/21 上午 3:04:36.990 com.apple.WebKit.Plugin.64[13691]: Error loading /Library/Internet Plug-Ins/EasyConnectPlugin.plugin/Contents/MacOS/EasyConnectPlugin:  dlopen(/Library/Internet Plug-Ins/EasyConnectPlugin.plugin/Contents/MacOS/EasyConnectPlugin, 262): Library not loaded: @loader_path/libCMS.dylib
  Referenced from: /Library/Internet Plug-Ins/EasyConnectPlugin.plugin/Contents/MacOS/EasyConnectPlugin
  Reason: image not found

基本上都是出现此报错,然后 VPN 连接失败。

于是谷歌 libCMS.dylib 到底是个什么东东,为何会找不到。但完全无解,所有搜索 libCMS.dylib 的内容都指向一个 liblcms.dylib 的库。

这到底是个什么牛逼哄哄的库?谷歌都找不到!抱着怀疑的心态,本地搜索此文件一发,Lucky!~还真给我找到了 ^O^

/Applications/EasyConnect.app/Contents/Resources/Libs 下发现此文件。那么问题好办了,只要把库文件放在正确的位置让程序启动时能找到就行了。

于是使用命令行工具 otool 分析程序,otool 需要 xcode-select --install 来安装,结果如下:

otool -L /Applications/EasyConnect.app/Contents/MacOS/EasyConnect
/Applications/EasyConnect.app/Contents/MacOS/EasyConnect:
    /usr/local/lib/libTevent.dylib (compatibility version 1.0.0, current version 1.0.0)
    @loader_path/libCMS.dylib (compatibility version 1.0.0, current version 1.0.0)
    /usr/local/lib/libecbase.dylib (compatibility version 7.0.0, current version 7.0.0)
    /System/Library/Frameworks/SystemConfiguration.framework/Versions/A/SystemConfiguration (compatibility version 1.0.0, current version 453.19.0)
    /System/Library/Frameworks/Cocoa.framework/Versions/A/Cocoa (compatibility version 1.0.0, current version 19.0.0)
    /System/Library/Frameworks/Foundation.framework/Versions/C/Foundation (compatibility version 300.0.0, current version 945.16.0)
    /usr/lib/libobjc.A.dylib (compatibility version 1.0.0, current version 228.0.0)
    /usr/lib/libstdc++.6.dylib (compatibility version 7.0.0, current version 56.0.0)
    /usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 169.3.0)
    /System/Library/Frameworks/CoreServices.framework/Versions/A/CoreServices (compatibility version 1.0.0, current version 57.0.0)
    /System/Library/Frameworks/CoreFoundation.framework/Versions/A/CoreFoundation (compatibility version 150.0.0, current version 744.18.0)
    /System/Library/Frameworks/AppKit.framework/Versions/C/AppKit (compatibility version 45.0.0, current version 1187.37.0)

可以看到 libCMS.dylib 的依赖路径是 @loader_path ,Google 此变量的意思,得到如下解释:

@loader_path

这个变量表示每一个被加载的 binary (包括可执行程序, dylib, framework 等) 所在的目录。在一个进程中,对于每一个模块,@loader_path 会解析成不用的路径。而 @executable_path 总是被解析为同一个路径(可执行程序所在目录)。比如一个会被多个程序调用的 plugin,位于 /path/Myfilter.plugin/Contents/MacOS/Myfilter,依赖 /path/Myfilter.plugin/Contents/dylib/libfoo.dylib

那么 libfoo.dylibINSTALL_PATH 可以设置为 @loader_path/../dylib,这样设置的话,不论 Myfilter.plugin 目录放到什么位置,libfoo.dylib 都能正确的被加载。

因为 @loader_path 的依赖路径由程序编译时指定,我们无法修改,但是我们可以将依赖拷贝至能调用到的地方。

libCMS.dylib 拷贝至 /Library/Internet Plug-Ins/EasyConnectPlugin.plugin/Contents/MacOS/EasyConnectPlugin/Applications/EasyConnect.app/Contents/MacOS/EasyConnect 下面。

然后我满怀期待登录 VPN,Lucky,问题解决。

总结

其实 VPN 登陆不上的问题只是一个小问题,一开始其实就应该有必要去查询系统日志,只有通过日志分析,才能知道原因。

其次,后面浏览 Cocoa 开发社区才知道,这种依赖调用的问题源于苹果修改了安全策略,阻止了原来的依赖调用,这才导致 EasyConnectPlugin 无法调用相关依赖。所以,遇到问题,还是要多思考,才能最终解决问题呀。

后记

ほんと最近 10 時過ぎには眠くなるんだけど成長期か!!!?!?!?!

身長あと 200000cm は欲しい, (#)‘ω‘(#)

最新的 VPN 插件出来了,此文作废,2333