homebrew 安裝 formula 的不同歷史版本——以安裝 node 為例 系統環境 macOS Mojave 10.14 Homebrew 1.8.0 Homebrew/homebrew core (git revision 586b0f; last commit 2018 10 27) H ...
homebrew 安裝 formula 的不同歷史版本——以安裝 node 為例
系統環境
- macOS Mojave 10.14
- Homebrew 1.8.0
Homebrew/homebrew-core (git revision 586b0f; last commit 2018-10-27)
Homebrew/homebrew-cask (git revision 76ddc; last commit 2018-10-27)
背景
最近 nodejs 發佈了 11.0.0 版本,而我是用 brew 安裝了名為 node 的這個 formula ,現在 brew upgrade
會自動將 node 更新到最新版本,於是我遇到了一些問題:
- 一些需要編譯安裝的依賴包還不支持 node@11 ;
- 不知道如何自動切換兩個 formula ( node 和 node@10 )之間的可執行文件;
- 是否能夠設定某個 formula 不自動更新?
在經過一番折騰後,現在我刪掉了 node 和 node@10 兩個 formula ,包括之前安裝的歷史版本(所以算是多走了一點彎路),想要同時保留 10 和 11 兩個大版本,並可方便切換。
前置條件
若下列條件不滿足,可能導致需要額外的操作來解決環境問題,這些操作不在本文討論範圍內:
- 只通過 homebrew 來安裝 node ;
- 沒有使用如 n / nvm 等 node 版本管理工具;
- 某種意義下連接性良好的網路。
適用情況
本文覆蓋瞭如下四種情況:
- 某個 formula 跟隨著更新上來,沒有運行過 cleanup 或 force uninstall ,想切回舊版本的(見關鍵點三);
- 全新安裝且只想安裝某個 formula (如 node 而非 node@10 ),但又想先用著舊版本的(見解決方案一);
- 某個 formula 在用的是舊版本,但想切換編譯選項(如
[email protected]
)重新安裝(同上); - 在兩個 formula 之間切換,如一個是 LTS 版的,一個是不穩定版的(見解決方案二)。
關鍵點
如何在 brew install / upgrade 時禁止自動更新
這一步很關鍵,否則我們總是會安裝到最新版本。只要在運行命令前,設置環境變數 HOMEBREW_NO_AUTO_UPDATE 為 1 就可以了,比如:
$ HOMEBREW_NO_AUTO_UPDATE=1 brew install node
也可以直接寫進 shell 配置文件中(如 .bashrc / .zshrc 等):
export HOMEBREW_NO_AUTO_UPDATE=1
查看某個 formula 的本地已安裝版本
有兩種方式可查看,一是 brew list --versions
,輸出以空格分隔,簡潔明瞭,推薦使用:
$ brew list node --versions
node 11.0.0 10.12.0
$ brew list zsh --versions |tr ' ' '\n'
node
11.0.0
10.12.0
二是 brew info
在查看 formula 信息時也可看到本地已安裝的版本:
$ brew info node
$ brew info node |grep -i '\/cellar'
/usr/local/Cellar/node/10.12.0 (3,668 files, 41.7MB)
/usr/local/Cellar/node/11.0.0 (3,665 files, 42MB) *
後面帶有的星號 * 表示當前激活的版本。
切換某個 formula 的版本
自有的 brew switch
命令即可,之前感覺 brew 較易上手,安裝後沒看文檔直接用到現在,所以不知道這個命令。命令的說明也很直觀:
brew switch formula version:
Symlink all of the specific version of formula's install to Homebrew prefix.
直接鍵盤一頓敲就行了,如 brew switch node 10.12.0
。
解決方案
安裝某個 formula 的歷史版本
切換到 brew 的倉庫目錄下
$ cd "$(brew --repo homebrew/core)"
查看某個 formula 的 git 歷史記錄
$ git log master -- Formula/node.rb
在裡面找到想要的歷史版本,比如這個就挺像我所需要的:
commit b801cc6b71e7c09448b4f823e493710665de68eb Author: BrewTestBot <[email protected]> Date: Thu Oct 11 00:12:43 2018 +0000 node: update 10.12.0 bottle.
檢出 git 歷史提交
$ git checkout b801cc6b71e7c09448b4f823e493710665de68eb
在禁止自動更新的前提下安裝這個 formula
$ HOMEBREW_NO_AUTO_UPDATE=1 brew install node [email protected]
由於剛纔第 3 步後處於分離頭指針狀態下,記得要切回來
$ git checkout master
升級這個 formula 試試
$ brew upgrade node
檢查當前版本,應該是最新的,現在再把它切回來
$ node -v v11.0.0 $ brew switch node 10.12.0 Cleaning /usr/local/Cellar/node/10.12.0 Cleaning /usr/local/Cellar/node/11.0.0 7 links created for /usr/local/Cellar/node/10.12.0 $ node -v v10.12.0
在兩個 formula 之間切換
我們也可以在 node 和 node@10 兩個 formula 之間切換文件鏈接。但是註意,這種方法可能會在運行 brew doctor
時產生警告,因為可能會有一個不是 keg-only 的包沒有被鏈接到 Cellar 中(如為了使用 node@10 而解除了 node 的鏈接),這個警告可以不去理會,但必須記住我們做過這樣的操作。
假定已經安裝了 node ,現在安裝 node@10 ,鍵盤一頓亂敲
$ brew install node@10
通常像這樣名字後面帶有版本號的 formula 都是 keg-only 的,簡單來說就是 brew 不會自動幫我們鏈接文件
先解除 node 的文件鏈接
shell $ brew unlink node
鏈接 node@10 的文件
$ brew link node@10
這時會提示這個包是 keg-only 的,需要加上
--force
選項。如果第 2 步沒有進行,還會提示你需要先解除 node 的鏈接,或者直接用--overwrite
選項覆蓋原有的鏈接。由於 npm 目錄一定需要覆蓋,所以我們總是可以打開--overwrite
選項:$ brew link node@10 --force --overwrite
檢查當前版本,在解決方案一中提到過了,方法也有很多種,此處略過。
後續問題
全局安裝的包支持的 node 版本可能不同
是的,這個問題一定會存在,建議通過切換 npm prefix 路徑解決,把不同版本 node 下安裝的全局包隔離開來。當然 nvm 等方案也可以解決問題,但本文是不一樣的煙火。$ mkdir -p ~/.npm-node10/npm-global $ npm config set prefix ~/.npm-node10/npm-global $ export PATH="$HOME/.npm-node10/npm-global/bin:$PATH"
手動切換確實比較繁瑣,可以寫個 shell 腳本把切換 formula 和切換 npm prefix 結合起來。
如何固定某個 formula 的版本?
雖然說不運行brew upgrade
就一直是固定的版本,但如果想只固定某個 formula 的版本而允許其他可以升級,也是極好的。自帶的 pin 、 unpin 命令就是用來解決這一問題,如:brew pin node
。如何刪除某個 formula 的舊版本?
儘管brew cleanup
可以刪除一個 formula 的所有舊版本,但通常我們可能只想刪除某幾個太舊且多餘的版本而不是全部。 brew 沒有提供這樣的命令,我們可以直接從 Cellar 裡面刪除:$ brew info node |grep -i '\/cellar' /usr/local/Cellar/node/10.12.0 (3,668 files, 41.7MB) /usr/local/Cellar/node/11.0.0 (3,665 files, 42MB) * $ rm -rf /usr/local/Cellar/node/10.12.0
初步測試未發現有副作用,歡迎討論和建議。
如何在升級時自動刪除舊版本?
根據brew upgrade
命令的說明,設置一個 HOMEBREW_UPGRADE_CLEANUP 環境變數就好了,比較簡單。
參考資料
- Tips and Tricks - Homebrew Documentation
- Homebrew terminology - Homebrew Documentation
- FAQ - Homebrew Documentation
- homebrew - how to install older versions - Stack Overflow
- Homebrew install specific version of formula? - Stack Overflow
- Using Homebrew how do I remove some specific versions but not all old versions - Stack Overflow
本文基於 知識共用署名-非商業性使用-相同方式共用 4.0 國際許可協議 發佈,歡迎引用、轉載或演繹,但是必須保留本文的署名 BlackStorm 以及本文鏈接 http://www.cnblogs.com/BlackStorm/p/homebrew-install-old-versions-take-node-for-example.html ,且未經許可不能用於商業目的。如有疑問或授權協商請與我聯繫。