MacOS软件包管理工具-HomeBrew

虽然 Mac OS X 自带了不少 Unix 下的开源软件,比如 vim, ruby, python, perl 等等,也自带了许多常用的库,包括 iconv, zlib 等等,但我们仍然有时会需要自己动手安装一些这样的软件或者库,要自动化这样的安装,现有最常见的选择是 MacPorts、Fink、HomeBrew。

其中 MacPorts 是基于源代码的包管理,并不在自己的库里储存软件的实际内容,只有一个定义如何编译代码的 Portfile 和一些专门针对这个平台的 patch;

而 Fink 则是 Apt 包管理系统在 Mac OS X 下的一个克隆,采用二进制分发,用户直接从 Fink 的仓库中下载安装软件。

优点和缺陷

MacPorts 基于源代码的管理优点是非常灵活,更新很快 (很多时候更新只需要修改一下 Portfile 里的版本号和压缩包校验码就可以),用户要订制安装也可以简单的通过修改 Portfile 实现,而且很多开源软件的安装配置会有多种模式 (典型的大都通过 configure 步骤配置),在 MacPorts 中可以方便地通过 variants 参数指定,而不必像二进制分发那样,在远程服务器上编译的时候就定死了。

而 MacPorts 的问题是,它希望自己安装的每套软件,所有的依赖都在它自己这个系统内 (一般就是你的 /opt/local) 解决,就算 Mac OS X 系统原生自带了满足依赖的库,它也坚决不用,这样就给你的系统增加了许多冗余,也客观增加了管理上的难度,典型的情况是:你的系统里装了两套 Python,该怎么管理外部安装的 Python 模块?比如通过 easy_install 或 setup.py 安装的,往往很难记住到底装到哪里了。

而 Fink 虽然不会这么自作主张地添加依赖,最大的问题是更新不够及时,这也是缺乏维护人手导致的。二进制安装的缺点在上面也提到了:不便定制。

所以 Homebrew 的出现,也许不是很及时,但在现在仍然是很必要的,它有这么一些优点:

  1. 尽可能的利用你的系统里自带的库,包括 zlib, OpenSSL, Python 等等,只要 Mac OS X 自带了,它就不会另装一份。
  2. 定制简单,通过用 Ruby 写的 Homebrew formula 来定制,甚至可以灵活的跟踪直接来自版本管理库的最新软件
  3. 用 Git 管理和同步自身
  4. 直接装在 /usr/local 下,这样可以少定义很多各种 PATH 环境变量

其中第一点尤为重要。好的,下面简单介绍一下 Homebrew 的安装,以及它是如何工作的。

推荐程度:Homebrew > MacPorts > pkgsrc > gentoo-prefix,Rudix 可以作为备胎,Fink 目前来看挺鸡肋。

Install Homebrew

由于Homebrew的安装地址可能变化,请到官方网站查看最新的安装方法。

安装过程需要输入root口令。

ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)"
==> This script will install:
/usr/local/bin/brew
/usr/local/Library/...
/usr/local/share/man/man1/brew.1
==> The following directories will be made group writable:
/usr/local/.
/usr/local/bin
==> The following directories will have their group set to admin:
/usr/local/.
/usr/local/bin

Press RETURN to continue or any other key to abort
==> /usr/bin/sudo /bin/chmod g+rwx /usr/local/. /usr/local/bin
Password:
==> /usr/bin/sudo /usr/bin/chgrp admin /usr/local/. /usr/local/bin
==> /usr/bin/sudo /bin/mkdir /Library/Caches/Homebrew
==> /usr/bin/sudo /bin/chmod g+rwx /Library/Caches/Homebrew
==> Downloading and installing Homebrew...
remote: Counting objects: 3616, done.
remote: Compressing objects: 100% (3449/3449), done.
remote: Total 3616 (delta 36), reused 685 (delta 27), pack-reused 0
Receiving objects: 100% (3616/3616), 2.91 MiB | 32.00 KiB/s, done.
Resolving deltas: 100% (36/36), done.
From https://github.com/Homebrew/homebrew
 * [new branch]      master     -> origin/master
HEAD is now at 0f175c1 points2grid: fix test
==> Installation successful!
==> Next steps
Run `brew help` to get started

首先,Homebrew 的原则是“No sudo”,也就是说,既然 Mac OS X (client 版本) 绝大部分情况下都是归你这个有管理员权限的用户,为什么在自己的 /usr/local 下安装程序还需要 sudo 呢?所以,首先:

sudo chown -R `whoami` /usr/local

然后可以正式开始安装,我推荐的安装方式是先用 git-osx-installer 装上 git,然后用 git 安装:

cd /usr/local
git init
git remote add origin https://github.com/Homebrew/homebrew
git pull origin master

这么做的实际作用是把你的 /usr/local 目录变成了一个本地 git 仓库,只不过这个仓库只跟踪跟 Homebrew 相关的更新,并不影响任何其他软件的安装。

这样安装会在 /usr/local 下创建 Library 这个目录,然后在 /usr/local/bin 中加入 brew 这个 ruby 脚本。

安装中问题解决

Connection refused错误

curl: (7) Failed to connect to raw.githubusercontent.com port 443: Connection refused

打开网站https://www.ipaddress.com/

查询一下 raw.githubusercontent.com对应的IP 地址,添加到/etc/hosts中后再试就可以了。

安装过程下载失败

安装过程说明:https://www.jianshu.com/p/3f521887543b

fatal: the remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

error: RPC failed; curl 18 transfer closed with outstanding read data remaining
fatal: The remote end hung up unexpectedly
fatal: early EOF
fatal: index-pack failed

Homebrew使用

Homebrew的可执行命令是brew,命令参数说明如下。

brew help
Example usage:
  brew [info | home | options ] [FORMULA...]
  brew install FORMULA...
  brew uninstall FORMULA...
  brew search [foo]
  brew list [FORMULA...]
  brew update
  brew upgrade [--all | FORMULA...]
  brew pin/unpin [FORMULA...]

Troubleshooting:
  brew doctor
  brew install -vd FORMULA
  brew [--env | config]

Brewing:
  brew create [URL [--no-fetch]]
  brew edit [FORMULA...]
  https://github.com/Homebrew/homebrew/blob/master/share/doc/homebrew/Formula-Cookbook.md

Further help:
  man brew
  brew home
brew home        # 访问Homebrew主页
brew update      # 更新Homebrew
brew doctor      # Homebrew的自我检测

brew list        # 查看已安装软件包
brew search      # 列出所有软件

brew search vim  # 查找vim软件包
brew info vim    # 查看vim包详细信息 
brew deps vim    # 查看vim包依赖关系
brew install vim # 安装vim软件包
brew uninstall vim # 安装vim软件包

brew outdated     # 列出过时的软件包(已安装但不是最新版本)
brew upgrade      # 更新过时的软件包(全部)
brew upgrade wget # 更新过时的软件包(指定)

定制自己的软件包

如果自己需要的软件包并不能在Homebrew中找到,怎么办呢,毕竟Homebrew是一个新生项目,不可能满足所有人的需求。当然,我们可以自行编译安装,但手工安装的软件包游离于Homebrew之外,管理起来不是很方便。

前文说过,Homebrew使用Ruby实现的软件包配置非常方便,下面简单谈一谈软件包的定制(假定软件包名称是bar,来自foo站点)。

  1. 首先找到待安装软件的源码下载地址:http://foo.com/bar-1.0.tgz
  2. 建立自己的formula: brew create http://foo.com/bar-1.0.tgz
  3. 编辑formula,上一步建立成功后,Homebrew会自动打开新建的formula进行编辑,也可用如下命令打开formula进行编辑:brew edit bar
  4. Homebrew自动建立的formula已经包含了基本的configure和make install命令,对于大部分软件,不需要进行修改,退出编辑即可。
  5. 输入以下命令安装自定义的软件包:brew install bar

关于Homebrew的其它功能,比如将自定义软件包提交到官方发布等,请参考Homebrew项目的主页及其Man Page。你将发现Homebrew不仅是“家酿”,更是“佳酿”。

GitHub API rate limit

Error: GitHub API rate limit exceeded for 220.166.254.65. (But here's the good news: Authenticated requests get a higher rate limit. Check out the documentation for more details.)
Try again in 56 minutes 17 seconds, or create an personal access token:
  https://github.com/settings/tokens
and then set it as HOMEBREW_GITHUB_API_TOKEN.

brew tap

brew 有个默认的仓库,brew tap 你可以看成是第三方的仓库。

安装rsync 3.1.1版本,解决中文文件名在日志中乱码问题。

brew tap homebrew/dupes
brew info homebrew/dupes/rsync
brew install homebrew/dupes/rsync

安装openvpn-connect

brew search openvpn-connect
==> Casks
homebrew/cask-versions/openvpn-connect-beta                                     homebrew/cask/openvpn-connect

openvpn-connect
Name: OpenVPN Connect client
https://openvpn.net/client-connect-vpn-for-mac-os/
brew tap homebrew/cask
==> Tapping homebrew/cask
Cloning into '/usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask'...
remote: Enumerating objects: 49, done.
remote: Counting objects: 100% (49/49), done.
remote: Compressing objects: 100% (37/37), done.
Receiving objects:   4% (22346/447900), 7.56 MiB | 18.00 KiB/s

brew cask install openvpn-connect

brew install homebrew/cask/openvpn-connect
==> brew cask install homebrew/cask/openvpn-connect
==> Downloading https://swupdate.openvpn.net/as/clients/openvpn-connect-2.7.1.107_signed.dmg
-=O=-               #    #     #     #
curl: (7) Failed to connect to swupdate.openvpn.net port 443: Operation timed out
Error: Download failed on Cask 'openvpn-connect' with message: Download failed: https://swupdate.openvpn.net/as/clients/openvpn-connect-2.7.1.107_signed.dmg

update Homebrew 太慢,更换Homebrew的更新源

更新源的选择

默认官方的更新源都是存放在GitHub上的,这也是中国大陆用户访问缓慢的原因,一般来说我们会更倾向选择国内提供的更新源,在此推荐中国科大以及清华大学提供的更新源。 替换更新源

# 替换brew.git:
$ cd "$(brew --repo)"
# 中国科大:
$ git remote set-url origin https://mirrors.ustc.edu.cn/brew.git
# 清华大学:
$ git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/brew.git

# 替换homebrew-core.git:
$ cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
# 中国科大:
$ git remote set-url origin https://mirrors.ustc.edu.cn/homebrew-core.git
# 清华大学:
$ git remote set-url origin https://mirrors.tuna.tsinghua.edu.cn/git/homebrew/homebrew-core.git

# 替换homebrew-bottles:
# 中国科大:
$ echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.ustc.edu.cn/homebrew-bottles' >> ~/.bash_profile
$ source ~/.bash_profile
# 清华大学:
$ echo 'export HOMEBREW_BOTTLE_DOMAIN=https://mirrors.tuna.tsinghua.edu.cn/homebrew-bottles' >> ~/.bash_profile
$ source ~/.bash_profile

# 应用生效:
$ brew update

诊断和重置

如果你之前折腾过不少导致你的Homebrew有点问题,那么可以尝试使用如下方案:

# 诊断Homebrew的问题:
$ brew doctor

# 重置brew.git设置:
$ cd "$(brew --repo)"
$ git fetch
$ git reset --hard origin/master

# homebrew-core.git同理:
$ cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
$ git fetch
$ git reset --hard origin/master

# 应用生效:
$ brew update  

换回官方源

重置更新源 某些时候也有换回官方源的需求

# 重置brew.git:
$ cd "$(brew --repo)"
$ git remote set-url origin https://github.com/Homebrew/brew.git

# 重置homebrew-core.git:
$ cd "$(brew --repo)/Library/Taps/homebrew/homebrew-core"
$ git remote set-url origin https://github.com/Homebrew/homebrew-core.git

完成更新源的更换后,我们可以使用brew upgrade将现有的软件进行更新至最新版本,这样便能很直接的看出速度上的变化了。

最后不要忘记brew cleanup将旧有的软件安装包进行清理

brew update 卡死解决方案

macOS 平台 Homebrew 更新 brew update 卡死,完美解决:https://www.cnblogs.com/tp0829/p/Homebrew.html

问题场景

原因分析

对于场景1我们可以选择Control-C直接终止当前前台update进程,然后brew就会接着执行install了.
但这样并不能"治本",其实造成上述两种情况的主要原因是资源访问太慢.
我们知道默认官方更新源在github.com上,因为一些原因,国内访问不太顺畅.
解决方案是我们可以选择国内镜像更新源.
国内镜像更新源推荐中国科大开源软件镜像站或清华大学开源软件镜像站.
某些同学可能要有疑问了,"我已经按照网上其他教程替换更新源了呀?怎么还不行?"
这里回答是,"可能你并没有更换彻底".
	输入brew update -verbose我们可以看到brew update工作的具体步骤.
$ brew update -verbose
Checking if we need to fetch /usr/local/Homebrew...
Checking if we need to fetch /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask...
Fetching /usr/local/Homebrew...
Checking if we need to fetch /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core...
Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-cask...
Checking if we need to fetch /usr/local/Homebrew/Library/Taps/homebrew/homebrew-services...
Fetching /usr/local/Homebrew/Library/Taps/homebrew/homebrew-core...
Already up-to-date.

我们可以看到它一共检查了Homebrew,homebrew-cask,homebrew-core,homebrew-services这几个文件.

而网上大部分教程替换更新源时往往只替换了Homebrew和homebrew-core这两个的源.

出问题,可能就出在homebrew-cask这个文件上,而我之前运行brew update -verbose显示卡死也的确是卡在这个地方.

所以知道了原因,我们只要把homebrew-cask这个文件的更新源也替换一下即可.

具体操作见中国科大镜像源:homebrew-cask.http://mirrors.ustc.edu.cn/help/homebrew-cask.git.html