最近闲来无事,决定将我的两台apple电脑升级成最新的苹果系统(macOS Catalina),当然,由于以前升级过多次mac系统,所以毫不犹豫从app store下载了最新的macOS Cetalina系统,当然,下载很快,安装也很快,过程就不说了,so easy。
1. 到底发生了什么事

不过安装完后,发生了一件不可思议的事,进入硬盘,发现硬盘里只有如下5个目录。my god,我的其他文件夹哪里去了?难道升级时给我格式化了?

靠!安装了macOS Catalina(10.15.4)后,文件系统都乱套了-LMLPHP

 转念一想,Apple应该不会这么变态,否则苹果总部应该早都被自己的用户给踏平了。于是立刻上网查是怎么回事,很过有了结果。原来从Catalina版本开始,Apple为了实现自己更安全的目的,将硬盘分成了两个卷(以前是一个卷),一个是系统卷,一个是数据卷。从下图所示的磁盘工具中就可以看出这一点。

靠!安装了macOS Catalina(10.15.4)后,文件系统都乱套了-LMLPHP

这有些类似于Windows的逻辑磁盘,不过与Windows不同,Catalina的系统卷和数据卷是共享整个磁盘的,只是进行了逻辑隔离。在默认情况下,系统卷只允许操作系统本身来写文件,对于其他用户(包括root用户)都是只读的。也就是说,使用sudo命令也不能向系统卷写入任何数据。

2. 我的文件到哪里去了呢?

现在关键的问题是,我的文件夹到哪里去了呢?其实Catalina会将用户自己创建的文件夹都放到如下的目录:
/Users/Shared/Relocated\ Items/Security

如果你的mac系统是中文状态,那么该目录就是下图所示的目录:

靠!安装了macOS Catalina(10.15.4)后,文件系统都乱套了-LMLPHP

切换到该目录,就会看到自己建立的所有的目录和相关文件。

这下放心了,只要文件都在就好,那么紧接着有面临另外一个闹心的问题,文件是都在,但路径全都变了,这就意味着以前设置的环境变量、word、excel、webstorm、goland等工具的打开历史已经没有意义了,所有的路径都需要重新设置,所有的文件都需要重新打开。天啊,我为什么要升级呢!

3. 恢复以前的目录结构

于是首先想到,是否将这些目录和文件移动到数据卷,路径是否会恢复呢?说做就做。

从磁盘工具中数据卷的装载点可以看到,数据卷的物理目录是/System/Volumes/Data,于是立刻切换到该目录,默认是空。

现在使用下面的命令将原来的目录移动到数据卷根目录(假设有一个名为test的目录要移动)。

sudo mv /Users/Shared/Relocated\ Items/Security/test /System/Volumes/Data

如果要移动其他目录,只要将test修改为相应的目录名即可。注意,这里必须用sudo,普通用户没有写权限。

注意:如果只在数据卷中移动数据,速度非常快,因为并不是真的移动的数据,而只是改变了目录的位置。

将所有的目录移动到/System/Volumes/Data后,会发现,目录并没有像期望的一样恢复到原来的样子,而是所有的目录前面都加了一个/System/Volumes/Data,也就是说,变成了/System/Volumes/Data/test。看样子要想其他法子了。

有网友提供的方法是将目录和文件直接移动到系统卷的根目录,这样就会恢复原貌了。这个方法当然可行,不过将数据从数据卷移动到系统卷,是非常费时的,因为这时真正的移动数据。而且系统卷要想写入数据,需要做特殊处理(一会再说),比较麻烦。而且以后也无法使用一般的方法在系统卷根目录添加任何目录和文件,感觉也比较别扭。

我认为最好的方式是文件和目录仍然放在数据卷,而在系统卷根目录创建指向数据卷相应目录的软链接,这样以后再创建新目录和文件时,只要在数据卷完成即可。如果哪个文件或目录要通过根(/)访问,可以在系统卷的根目录创建一个软链接,这样才是是鱼和熊掌可兼得之法。

不过系统卷默认即使使用root用户也无法写入文件,不过可以将安全监测关掉。具体方法如下:

1. 重启mac电脑,按着Command + R,等待进入安全模式;
2. 进入安全模式后,在上方菜单打开终端,然后执行csrutil disable命令关掉SIP(系统完整性保护),重启电脑,正常进入系统;
3. 在终端执行sudo mount -uw / 命令将系统卷根目录设为可写状态;

经过这3步,系统卷根目录已经可写了,但仍然需要使用sudo命令。如果操作完,想重新打开SIP,可以再次进入安全模式,然后执行csrutil enable 命令即可,当然,不打开也没问题。现在假设数据卷有一个名为backup的目录,为backup在系统卷根目录创建软链接的方法如下:

首先在终端进入系统卷根目录,然后执行下面的命令
sudo ln -s /System/Volumes/Data/backup backup

为其他目录在系统卷根目录创建软连接的方法类似。ok,现在我们可以为需要通过系统卷根目录访问的目录和文件创建软链接了,都搞定后,我们会发现所有的路径都恢复正常了。

4. 编译程序又出错了

如果你是普通用户,那么到这里就完全搞定了,不过对于程序员来说,还远远没有结束。由于我要使用go语言开发相关项目,于是试一试go语言是否可以编译通过,结果.....,竟然输出了下面的错误:

_cgo_export.c:3:10: fatal error: 'stdlib.h' file not found

这个错误我以前遇到过,是由于/usr/local目录中没有stdlib.h文件导致的,在上一个macOS版本中,可以在磁盘上搜索macOS_SDK_headers_for_macOS_10.14.pkg文件,然后安装即可。不过在Catalina中,并没有macOS_SDK_headers_for_macOS_10.14.pkg文件,当然macOS_SDK_headers_for_macOS_10.15.pkg也没有。不过在/Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk目录下却发现了已经安装好的相应文件。

注意:如果没有该目录或相关文件,可以使用 xcode-select --install命令安装

这里又要用到软链接了,其实go使用cgo编译时,会到如下两个目录搜索相关文件:
/System/Library/Frameworks/CoreFoundation.framework
/System/Library/Frameworks/Security.framework

所以只要通过软链接,将相关的目录和文件链接到这两个目录即可,于是有了如下的解决方案:

在终端进入/System/Library/Frameworks/CoreFoundation.framework目录,然后执行下面两条命令:
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Headers Headers

sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/CoreFoundation.framework/Versions/A/Modules Modules

再进入/System/Library/Frameworks/Security.framework目录,然后执行下面两条命令:
sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Security.framework/Headers Headers

sudo ln -s /Library/Developer/CommandLineTools/SDKs/MacOSX10.15.sdk/System/Library/Frameworks/Security.framework/Modules Modules

完成以上步骤后,新系统就一切恢复如常了,真是虚惊一场。最后建议:用户的数据最好还是放在数据卷中,如果非要通过系统卷的根(/)访问,可以在根目录创建软链接,但不要忘了打开SIP哦!

靠!安装了macOS Catalina(10.15.4)后,文件系统都乱套了-LMLPHP

04-24 10:11