用 Homebrew 管理 Mac 上的所有软件

2021年11月20日星期六 / ,
摘要:
软件装得乱、删不干净、换电脑又要重装一遍,于是我决定把 Mac 上能交给 Homebrew 的软件全都交给它,再用一个 Brewfile 记下来。

用 Mac 这几年,软件装得越来越乱。有的是从官网下载的 dmg,有的是从 App Store 装的,有的是用 Homebrew 装的命令行工具,还有一些是某个安装包顺手塞进来的。时间一长,我自己都说不清楚电脑里到底装了什么、每个软件是从哪来的。

删软件也是一件麻烦事。Mac 上卸载一个应用,大多数时候就是把它拖进废纸篓,但是它在 ~/Library 下面留下的配置、缓存和各种支持文件,并不会跟着一起删掉。所以电脑用久了,~/Library 里会堆着一大堆早就不用的软件留下的东西。最终只能用天价的 CleanMyMac 之类的工具去清理,或者自己一个个去找。

再加上最近要把环境搬到一台新的 Apple Silicon 的 Mac 上,如果还像以前那样一个个去官网下载重装,实在太累了。于是我决定,以后 Mac 上的软件,只要 Homebrew 能装的,就全部用 Homebrew 来装,然后用一个 Brewfile 把它们都记下来。

在 Apple Silicon 上安装 Homebrew

Homebrew 从 3.0 开始原生支持 Apple Silicon,安装命令和以前一样。

Shell
/bin/bash -c "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/HEAD/install.sh)"

不过有一点和 Intel 的 Mac 不同,Apple Silicon 上 Homebrew 默认装在 /opt/homebrew,而不是原来的 /usr/local。所以 /opt/homebrew/bin 默认是不在 PATH 里的,装完之后要在 ~/.zprofile 里加上这一行。

Shell
eval "$(/opt/homebrew/bin/brew shellenv)"

brew shellenv 会输出一组环境变量,包括 PATH、MANPATH 这些,所以用 eval 执行一下就都设置好了。

formula 和 cask

Homebrew 里的软件分成两种。formula 是命令行工具和库,比如 git、ripgrep,cask 则是带图形界面的应用,比如 Chrome、VS Code。

Shell
brew install ripgrep
brew install --cask visual-studio-code

以前装 cask 用的是 brew cask install,去年底的 2.6.0 开始,所有 brew cask 命令都被废弃了,统一换成了 brew 命令加上 --cask,所以网上一些老教程里的写法现在已经不能用了。

字体也可以用 cask 来装,只是要先添加 homebrew/cask-fonts 这个 tap。

Shell
brew tap homebrew/cask-fonts
brew install --cask font-jetbrains-mono

卸载得干净一点

用 Homebrew 来管理 cask,一个很大的好处就是卸载。普通的卸载只会删掉应用本身,和拖进废纸篓差不多。

Shell
brew uninstall --cask some-app

但是加上 --zap 之后,Homebrew 还会按照 cask 里写好的 zap 规则,把这个应用在 ~/Library 下面留下的偏好设置、缓存、支持文件一起删掉。

Shell
brew uninstall --zap --cask some-app

当然,不是每个 cask 都写了 zap 规则,不过常用的大部分软件都有。至少比我自己去 ~/Library 里一个个翻要靠谱得多。

Brewfile

如果只是用 Homebrew 装软件,那么迁移的时候还是得自己记住装过什么。好在 Homebrew 有一个 bundle 子命令,可以把当前装的所有东西导出成一个 Brewfile。

Shell
brew bundle dump --describe --force --file=~/dotfiles/Brewfile

--describe 会在每一行上面加一句软件的简介,以后回头看的时候,不至于对着一个陌生的名字想不起来它是干什么的。--force 则是覆盖已有的文件。导出来的 Brewfile 大概长这样。

Ruby
tap "homebrew/bundle"
tap "homebrew/cask"
tap "homebrew/cask-fonts"
tap "homebrew/core"
# Clone of cat(1) with syntax highlighting and Git integration
brew "bat"
# Modern replacement for 'ls'
brew "exa"
# Simple, fast and user-friendly alternative to find
brew "fd"
# Command-line fuzzy finder written in Go
brew "fzf"
# GitHub command-line tool
brew "gh"
# Search tool like grep and The Silver Searcher
brew "ripgrep"
# Mac App Store command-line interface
brew "mas"
# Password manager that keeps all passwords secure behind one password
cask "1password"
cask "font-jetbrains-mono"
# Web browser
cask "google-chrome"
# Terminal emulator as alternative to Apple's Terminal app
cask "iterm2"
# Control your tools with a few keystrokes
cask "raycast"
# Messaging app with a focus on speed and security
cask "telegram"
# Open-source code editor
cask "visual-studio-code"
mas "Xcode", id: 497799835

最后一行的 mas 是 App Store 的命令行工具,有些软件只在 App Store 上架,比如 Xcode,这样也能一起写进 Brewfile 里,后面的数字就是它在 App Store 的 ID。

我把这个 Brewfile 放进了自己的 dotfiles 仓库里,每次装了或者删了什么,就重新 dump 一次,然后提交。这样仓库里永远有一份当前电脑上软件的完整清单。

在新电脑上恢复

到了新电脑上,装好 Homebrew,把 dotfiles 仓库克隆下来,然后一条命令就能把 Brewfile 里的东西全部装回来。

Shell
brew bundle --file=~/dotfiles/Brewfile

它会依次添加 tap、安装 formula 和 cask,已经装过的会直接跳过,所以中途断了也可以放心重新跑。cask 一多,整个过程会花上一段时间,不过这段时间完全不用管它,比自己一个个下载安装要省心太多了。

反过来清理

Brewfile 除了能用来安装,还可以反过来清理。brew bundle cleanup 会列出那些装在电脑上、但是没有写进 Brewfile 的东西。

Shell
# 只列出来,不删除
brew bundle cleanup --file=~/dotfiles/Brewfile

# 确认没问题之后再真的删除
brew bundle cleanup --force --file=~/dotfiles/Brewfile

所以有时候我会反过来操作,直接在 Brewfile 里删掉不想要的软件,再运行一次 cleanup,电脑上就跟着一起删掉了。这样 Brewfile 和电脑上的状态就能一直保持一致。

另外 brew leaves 也很好用,它只列出那些不是被别的 formula 依赖进来的、我自己主动安装的 formula,想看看自己到底装了哪些工具的时候,比 brew list 清楚很多。

一些习惯

  • 能用 cask 装的应用,就不再从官网下载 dmg。
  • 只在 App Store 有的应用,用 mas 装,同样写进 Brewfile。
  • 每次装完或者删完软件,就 dump 一次 Brewfile 并提交。
  • 更新的时候统一用 brew upgrade,cask 也会一起更新,只有那些自己会自动更新的应用需要额外加 --greedy。

这样坚持下来,电脑上的软件就都有了来源,换电脑也只需要一个仓库加一条命令。新电脑到手那天,我从克隆仓库到软件全部装好,中间基本就是在等下载。

  • Loading...
  • Loading...
  • Loading...
  • Loading...
  • Loading...