rcmdnk's blog
Last update

AWSの基本・仕組み・重要用語が全部わかる教科書 (見るだけ図解)

Homebrewでいつも通りupgradeを行ったところ、awscliがエラーを出すようになったので ちょっと前のバージョンを使えるようにした話。

Homebrewでのバージョン管理

Homebrewでは以前はHomebrew-versionsというtapが存在し、古いバージョンのインストールが出来たりしました。

現在はそれもなくなり、基本的に最新バージョンのものしかインストールできない仕様になっています。

一部、Pythonなど複数のよく使われるメジャーバージョンがある場合のみ、[email protected]のような@付きの名前で 違うバージョンがインストールできるようになってはいます。(@なしがいずれかに対応するようになっている。)

普通のFormulaはちょっと前のバージョンを入れたい、と思っても 公式でやる方法は用意されていません。

なのでちょっと手動で色々とやる必要があります。

awscliのエラー

追記: 2023/01/20

以下のエラーはどうもawscli自体に問題があったというより、環境(恐らくPythonの)がおかしな状態になっていたようです。

別件でHomebrewを入れ直してawscliを入れたところ問題なく動きました。

2.9.1まで遡って入れ直して試してみましたがやはりエラーは起きませんでした。

追記ここまで

今回awscliでエラーが出て前のバージョンを使わなくてはならなくなったのが発端です。

最新の2.9.1にアップグレードすると

$ aws --version
Traceback (most recent call last):
  File “/opt/homebrew/bin/aws”, line 19, in <module>
    import awscli.clidriver
  File “/opt/homebrew/Cellar/awscli/2.9.1/libexec/lib/python3.11/site-packages/awscli/clidriver.py”, line 43, in <module>
    from awscli.help import ProviderHelpCommand
  File “/opt/homebrew/Cellar/awscli/2.9.1/libexec/lib/python3.11/site-packages/awscli/help.py”, line 20, in <module>
    from docutils.core import publish_string
ModuleNotFoundError: No module named ‘docutils’

といったエラーが出て使えなくなってしまいました。

問題が起こっているのはmacOSの環境で、M1 Macですが、Rosetta2を使ったx86_64の環境でも同じエラーが出ました。

WindowsのWSL環境では出なかったのでmacOSでの問題のようです。

毎日brew upgradeをかけていますが、どうやら2.9.1に変更が入ったあたりが問題っぽい。

History for Formula/awscli.rb - Homebrew/homebrew-core

いくつか試してみたところ、

awscli: depend on docutils · Homebrew/[email protected]

のcommitの前までならエラーが出ませんでした。

2.9.0でも上のcommit以降では同様のエラーが出ました。

上のエラーでもdocutilsに関して文句を言っているのでおそらくこの変更が原因。

まだIssueなどに上がってないことから、もしかしたら自分の環境固有の問題かもしれませんが、まだFormulaがアップデートされたばかりなので、今後同じようなエラーが出て問題が発覚するかもしれません。

とりあえず使えないと困るのでなんとかしようと。

Homebrewで古いバージョンのインストール

上にも書いたように、現状のHomebrewでは常に最新バージョンを常に使うことを想定して古いバージョンを使う方法は公式には用意されていません。

また、以前はFormulaのURLをを直接指定してのインストールなどもできましたが、現在は

$ brew install https://raw.githubusercontent.com/Homebrew/homebrew-core/b72dc5a4db9c20cbda5c50a8e196943cca34d8f6/Formula/awscli.rb
Error: Installation of awscli from a GitHub commit URL is unsupported! `brew extract awscli` to a stable tap on GitHub instead.

といった感じでダメです。

さらに、ローカルにダウンロードして直接指定しても

$ brew install ./awscli.rb scli.rb
Warning: No available formula with the name “./awscli.rb”. Did you mean awscli?
==> Searching for similarly named formulae...
This similarly named formula was found:
awscli
To install it, run:
  brew install awscli
  ==> Searching for a previously deleted formula (in the last month)...
  Error: No previously deleted formula found.

となってできなくなっています。

したがってきちんとTapした形でFormulaを用意しないといけません。

すごく簡単には/opt/homebrew/Library/Taps/homebrew/homebrew-core/Formulaの中のawscli.rbを以前のものと置き換えて上げてbrew installとかすれば古いバージョンがインストールできます。

ですが、これだとbrew updateなどがうまくいかなくなります。

別途自分でTapレポジトリを作ってawsclimod.rbみたいな自分用のFormulaを作ることも考えられますが結構手間です。

なので、一旦古いFormulaを取り出して、元にもどすような事を考えます。

TapはGitのレポジトリとして管理されているので

$ brew rm awscli # 一旦現バージョンを削除
$ cd /opt/homebrew/Library/Taps/homebrew/homebrew-core
$ git log Formula/awscli.log # 必要なcommitを探す
$ git checkout b72dc5a4db9c20cbda5c50a8e196943cca34d8f6 # 必要なcommitの状態に移行
$ brew install awscli # 古いバージョンをインストール
$ aws --version
aws-cli/2.9.0 Python/3.11.0 Darwin/21.6.0 source/arm64 prompt/off

とすることで古いFormulaを取り出してインストールすることができます。

ただ、このままだとbrew updateなどがうまくいななくなるので元のmasterブランチに戻す必要があります。

そのまま戻してしまうとbrew upgradeで2.9.1になってしまいます。

とどめておくには以下の2つの方法があります。

ピンどめする

Homebrewにはbrew pinというコマンドがあり、現在インストールされているパッケージを、アップデートされたバージョンがあってもそのまま留めておく、という機能があります。

これを使い、上の状態で、

$ brew pin awscli
$ git checkout master

とすることで、今後awscliを2.9.0のまま保つことができます。

この状態でupdate/upgradeしてみると

$ brew update
Updated 2 taps (homebrew/core and homebrew/cask).
==> Outdated Formulae
awscli
You have 1 outdated formula installed.
You can upgrade it with brew upgrade
or list it with brew outdated.

$ brew upgrade
Error: Not upgrading 1 pinned package:
awscli 2.9.1
==> No packages to upgrade

みたいな感じでエラーにはなりますが、awscliに関してはバージョンを保ったままにできます。

もし問題が治ったバージョンがリリースされたらunpinコマンドを使って、

$ brew unpin awscli
$ brew update && brew upgrade

で最新バージョンにすることができます。

古いバージョンを残して直接使う

上の方法だとbrew updateなどでエラー終了になるのがちょっと気持ち悪いところです。

また、最新バージョンを試そうと思うと一旦unpinしてインストールした後、だめだったら 再び最初の方法で古いバージョンを入れ直す必要があります。

そこで、別の方法として、古いバージョンを残しておき、それを直接使う方法を考えます。

Homebrewではパッケージのバージョンごとに別のディレクトリを作りインストールを行い、そこから/opt/bin/などへのシンボリックリンクをはっています。

awscliであれば/opt/homebrew/Cellar/awscli/2.9.0bin/awsなどがあります。

ただし、現在のHomebrewではパッケージの新しいバージョンがインストールされると古いバージョンは即座に消されるようになっています。

したがって上のようなエラーに気づいてから古いバージョンを使おうと思ってもすでに消されています。

これに関しては

$ export HOMEBREW_NO_INSTALL_CLEANUP=1

をしてからbrewコマンドを使うことで古いバージョンを消さないようにできます。

これを使って、まず上の方法に従って2.9.0をインストールした後、

$ git checkout master
$ export HOMEBREW_NO_INSTALL_CLEANUP=1
$ brew update & brew upgrade

とすると /opt/homebrew/Cellar/awscli/2.9.02.9.1が残ったままになります。

/opt/homebrew/bin/awsは2.9.1のものになってしまいますが、 2.9.0の実行ファイルも/opt/homebrew/Cellar/awscli/2.9.0/bin/awsに残っています。

そこで

$ export PATH=/opt/homebrew/Cellar/awscli/2.9.0/bin:$PATH

とすればawsと呼ぶことで2.9.0の方を使えるようになります。

この方法であればbrew update/brew upgradeは問題なく行えますし、 最新のawscli

$ /opt/homebrew/bin/aws --version

とすればすぐに使えるのでチェックも簡単にできます。

厳密には/opt/homebrew/Cellar/awscli/2.9.0/etcの下に補完用のファイルがあったりして このあたりも使えるようにしたほうが良いかもしれませんが、 最新バージョンとマイナーバージョンまで同じものでもあり大きな違いはなさそうなのでとりあえず実行ファイルだけ2.9.0を直接指定して動かすようにしています。

上の設定を毎回やるのは面倒なので、.bashrcなどに

export HOMEBREW_NO_INSTALL_CLEANUP=1
export PATH=/opt/homebrew/Cellar/awscli/2.9.0/bin:$PATH

を追記しておきます。 特にHOMEBREW_NO_INSTALL_CLEANUPの設定は忘れると2.9.0のディレクトリがbrew upgradeなどで消えてしまうので注意。

逆に、この設定をし続けると他のFormulaも古いファイルが残り続けるのでディスクが圧迫されてる場合にはちょっと注意が必要です。 場合によっては一度HOMEBREW_NO_INSTALL_CLEANUP=0brew upgradeなどを行って掃除してサイドawscliの2.9.0を入れたりする必要があるかもしれません。

ちなみに以前はbrew switchという、古いバージョンへの切り替えコマンドがありましたが、 このコマンドも古いバージョンを即座に消すようになった流れの中で削除されていて現在は使えません。

Sponsored Links
Sponsored Links

« Vimでコピペ用に色々消す Pythonでdocstringの一部を継承する方法 »

}