在Mac上使用HomeBrew
安装telnet
时候出现错误,于是,就来探究一番。
执行命令 brew install telnet
,错误如下:
那么 /usr/local/Cellar
这个目录是做什么用的呢? 从Homebrew的官网上面可以看到,Homebrew是先将文件分别安装到独立目录之后,再将其文件软链接至Cellar
目录下面。也就是Cellar目录是要放软链接的。
但是从上图中的错误可以看到,错误为Operation not permitted
即在创建 /usr/local/Cellar
目录的时候似乎碰到了权限错误。 那么,接下来我们来验证一下。
既然是最终要放置安装好文件软链接的文件夹出现了问题,那么在使用Homebrew
安装其他工具的时候也会出现同样的错误。这里,我再安装下 ruby
试试。
brew install ruby
结果如我们所设想的一样
看图我们发现,在这个过程中几个组件都碰到了同样的问题。接下来,我们分析下这个权限问题的原因是什么。
首先,我们查看下 /usr/local
这个目录的信息看能不能发现什么。这里,可以使用命令 ls
,即
ls -ld /usr/local
其中参数表示
-l
: 除了文件名以为,还可以将文件的权限、所有者、文件大小等信息详细列出来-d
: 即 -directory
将目录像文件一样显示,而不是显示其下的文件这样我们很明显可以看出,所有者是 root
, 所数组是wheel
。而且只有所属者root
具有写的权限,这也就是出现权限问题的原因。顺便说下,这里有个wheel
组,这个是用来做什么的呢?引用维基百科上关于Wheel
词条的解释如下:
In computing, the term wheel refers to a user account with a wheel bit, a system setting that provides additional special system privileges that empower a user to execute restricted commands that ordinary user accounts cannot access.
Modern Unix systems generally use user groups as a security protocol to control access privileges. The wheel group is a special user group used on some Unix systems to control access to the su or sudo command, which allows a user to masquerade as another user (usually the super user).
解释了有关wheel
的来源和wheel group
的意思,其实就是一组可以获取特殊权限的用户,具体可以参考 维基百科的wheel词条。
理论上来说,使用sudo
来执行root权限肯定可以安装的,但是homebrew
是禁止使用sudo
进行操作的,因为这个操作太危险了。那要是把 /usr/local
目录的所有者改成当前用户呢,这样也就使当前用户执行brew
所需要的操作了。很多人解决的办法是 :
sudo chown -R $(whoami) /usr/local/
我现在的系统是 macOS Mojave (10.14.2)
,执行结果如下:
chown: /usr/local/: Operation not permitted
很明显,最新的系统已经禁止了这种操作。
这让我想起了引起这个问题的起因,就是因为系统对 /usr/local
目录增强了安全性。既然是操作系统的改进,那必定是以后的趋势,再改回我觉得并不是个最好的解决办法。突然想到好像在这台电脑上挺久没有用过HomeBrew
了,而且这个问题应该是个大部分人都会遇到的问题。作为一个活跃的开源项目,我想这个问题应该早都解决了吧。于是,从brew
官网上面找到了卸载的代码 :
ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/uninstall)"
顺利卸载,然后重新安装:
/usr/bin/ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
也顺利完成。
再次使用 ls -ld /usr/local/
进行查看
local
目录的权限以及所有人等都没有发生任何变化.
但是,查看 /usr/local/
内部的文件可以看到
其中,我们之前所需要的Cellar
目录已经创建完成了,并且其所数组
也具有了写的权限。当然,除了Cellar
目录,其他所需要的目录页一起创建了,结合安装时候的打印日志,如下:
这样,在最新的HomeBrew
中,安装的时候就将需要的目录都已经创建完成并且分配了所需的权限,那么在用brew
去安装其他软件的时候就可以不需要sudo
权限直接进行了。我想,应该是没有问题了。
再次安装telnet
brew install telnet
果然,安装成功,没有再提示任何错误。
telnet
已经安装在了Cellar
目录中。
最终可以得出,这个问题出现的起因是因为在Mac OS 10.12
和 10.14
中将/usr/local
的安全性加强引起的,不允许更改所有人等(其中10.14
比10.12
有所加强,可见趋势如此)。最新的HomeBrew
安装包通过安装的时候直接创建所需要的目录以及分配足够的权限来解决。
这点我们可以通过下载HomeBrew
的安装脚本来证实。很简单,使用curl
把安装脚本里面的shell
脚本下载到本地
curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install > brew.sh
打开brew.sh
,大致看下会发现代码中加入了对10.14
版本和10.12
的定义
这样就可以判断Mac
系统在10.14
和10.12
做了比较大的修改,需要专门针对这个脚本作更改。
在安装brew
的过程中,需要输入密码来继续,在安装脚本中也很容易看到很多sudo
命令的语句,有兴趣可以自己来细看。
如果遇到这个问题,在HomeBrew
更新之前我们不得已使用各种奇淫技巧来解决。但是既然现在已经有了更安全更好的解决方案,在遇到相同的问题时我建议直接卸载之前的brew
,然后安装最新的。