用 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...