エックスサーバーは安価なレンタルサーバですがsudoによる管理者操作ができないためパッケージマネージャからシステム領域に新規パッケージをインストールできません。そこでlinuxbrew(現在はHomebrewへ統合)をログインユーザとしてビルドしbrewを使ってパッケージ管理を行う記事が色々書かれています。
ここでは2021年8月現在のやり方でpipenvがbrewでインストールできpythonのプロンプトが表示されるようになるまでの流れをメモとしてまとめておきます。
linuxbrewのインストール
まずbrewをインストールする必要があり、次を使うことになります。しかし実行するとOSにインストールされているgitとcurlのバージョンが古くinstall.shが期待するオプションが実行できないため、バージョンを確認する部分で警告が出ます。
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
表示される警告の例
Error: Please update your system curl.
Minimum required version: 7.41.0
Your curl version: 7.29.0
Your curl executable: /usr/bin/curl
Error: Please update your system Git.
Minimum required version: 2.7.0
Your Git version: 1.8.3.1
Your Git executable: /usr/bin/git
yum, apt などのパッケージマネージャがあればupdateして最新バージョンを取得することもできますがそれらがインストールされている場所に上書きする権限がないのでできません。したがって自分のワークディレクトリにアップデートしたいツール、具体的には git, curl, opensslをソースからビルドすることになります。
git, curl, opensslのインストール方法
まずワークディレクトリの構成を考えます。例えばOSのサードパーティのツールが/opt などにインストールされることを踏まえると、~/opt に入れていくと分かりやすそうです。
各ツールをビルドするには、それぞれのソースコードを取得してmakeする手順を繰り返していくことになります。ソースコードはビルドが終わったら消してもいいので、ワークの直下に次のようなディレクトリを作ることにします。各サブフォルダの配下にはビルドした実行形式・ライブラリ・ドキュメントがデイレクトリを分けてインストールされます。
# インストール先
~/opt/curl
~/opt/git
~/opt/ssl
# ソースと展開先
~/curl-7.65.3.tar.gz
~/curl-7.65.3\
~/git-2.17.0.tar.gz
~/git-2.17.0\
~/openssl-1.0.2k.tar.gz
~/openssl-1.0.2k\
ツールに付与されたバージョンはこれを執筆時点でテストしたXサーバーの環境で動作したものです。opensslはhttps対応で他のツールの依存があるためビルドします。参考まで使ったXサーバーのOSを示します。
$ uname -a
Linux XXXXX.xserver.jp 5.4.0-73-generic #82~18.04.1-Ubuntu SMP Fri Apr 16 15:10:02 UTC 2021 x86_64 x86_64 x86_64 GNU/Linux
最終的に作業の流れは次のようになります。
- openssl, curl, git のダウンロード
- 上の順に各ツールのビルド
- linuxbrewのインストール
またビルド時のコンパイラフラグとして次の二つを意識しました。
- Position Independent Code(-fPIC)
- sharedライブラリのビルド(--enable-shared)
前者はCFLAGSとして環境変数に設定、後者はconfigureにあたえるオプションとして対応しました。
$ export CFLAGS=-fPIC
opensslのビルド
$ wget http://www.openssl.org/source/openssl-1.0.2k.tar.gz
$ tar xvfz openssl-1.0.2k.tar.gz
$ cd openssl-1.0.2k
$ ./config shared --prefix=$HOME/opt/ssl --openssldir=$HOME/opt/ssl
$ make
$ make install
#確認
$ which openssl # $HOME/opt/ssl/bin などPATHに含まれるパスを表示
curlのビルド
$ wget https://curl.haxx.se/download/curl-7.65.3.tar.gz
$ tar zxvf curl-7.65.3.tar.gz
$ cd curl-7.65.3
$ ./configure --with-ssl=$HOME/opt/ssl --enable-libcurl-option --prefix=$HOME/opt/curl --enable-shared
$ make
$ make install
# 確認
$HOME/opt/bin/curl -V
gitのビルド
opensslがconfigureから見えていないと、git-2.17.0に git-git-remote-https 実行形式がビルドされません。--with-opensslに正しいディレクトリを与える必要があります。次が必須かは分かりませんが次を設定してconfigureしていました。
$ export LDFLAGS="-L$HOME/opt/ssl/lib -L$HOME/opt/curl/lib"
$ wget https://www.kernel.org/pub/software/scm/git/git-2.17.0.tar.gz
$ cd git-2.17.0
$ ./configure --prefix=$HOME/opt/git --with-openssl=$HOME/opt/ssl --with-curl=$HOME/opt/curl --enable-shared
# ビルドをやり直した場合、次をしてからmakeを実施
# $ make clean
$ make
$ make install
# 確認
$ $HOME/opt/git/bin/git clone https://github.com/<リポジトリ>
linuxbrewのインストール
上が終わるとようやく元々のスクリプトが動作するようになるはずです。強制的に自分でビルドしたgit/curlを使ってインストーラが実行されるようにするため、次の環境変数を設定します。
$ export HOMEBREW_FORCE_BREWED_GIT=True
$ export HOMEBREW_FORCE_BREWED_CURL=True
$ sh -c "$(curl -fsSL https://raw.githubusercontent.com/Linuxbrew/install/master/install.sh)"
brew install pipenv
ようやくbrewが使えるようになったはずですが、実際にパッケージをインストールしようとするとビルドしたgit, curlを使ってくれません。
$ brew install pipenv
/home/XXXXX/.linuxbrew/opt/curl/bin/curl: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory
Error: Please update your system curl.
Minimum required version: 7.41.0
Your curl version: 7.29.0
Your curl executable: /usr/bin/curl
/home/XXXXX/.linuxbrew/opt/curl/bin/curl: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory
/home/XXXXX/.linuxbrew/opt/curl/bin/curl: error while loading shared libraries: libssl.so.1.0.0: cannot open shared object file: No such file or directory
brewの中身を少し調べたところ、git, curlを呼び出しているのは次のようなファイルのようです。
$HOME/.linuxbrew/Homebrew/Library/Homebrew/cmd/update.sh
$HOME/.linuxbrew/Homebrew/Library/Homebrew/brew.sh
上のファイルやbrewの振る舞いを見ると、~/.linuxbrew/opt/以下に依存ツールを格納する場所があるようです。ここに~/opt/へのシンボリックリンクを作っておきます。
$ cd ~/.linuxbrew/opt
$ ln -s ~/opt/curl .
$ ln -s ~/opt/git .
上を追記してもまだXサーバーにバンドルのcurl, gitを見に行きます。シェルスクリプトの中でPATH環境変数を設定すれば~/optにインストールしたものが使われるかを調べてみましたがbrew実行後に上書きされてしまいます。brewの設定を上書きするためには規定されたやり方で行う必要があります。具体的にはHOMEBREW_で始まる環境変数を使ってbrewの設定を使わせないようにします。先のHOMEBREW_FORCE_BREWED_{GIT,CURL}環境変数の他に、ここで起きてている問題を解消するには次の非公式フラグを設定します。
$ HOMEBREW_NO_ENV_FILTERING=True
これでbrew installが動作するようになりました。起動時には毎回次のような警告が表示されます。またこのような使い方は動作保証されていないためアップデート時は注意が必要です。
$ brew install pipenv
Warning: HOMEBREW_NO_ENV_FILTERING is undocumented, deprecated and will be removed in a future Homebrew release (because it breaks many things)!
追記:pipenv固有の問題
pipenv のビルドはgcc@5がないためエラーとなります。このリンクにある次の方法で回避できます。
$ brew install --force-bottle gcc@5
次のエラー(Error: undefined method
fetch' for nil:NilClass`)も回避策が示されています。
$ brew edit gcc@5
# 変更箇所
(変更前)
bottle do
sha256 cellar: :any, high_sierra: "dcc9059b725fd7c87842287bbedf60a28745417652d42a300dcd944e15986f36"
sha256 x86_64_linux: "cd94b6bc2189df7861c2c32c480f777984865dbab4107f493188feda5a05b80d"
end
(変更後)
bottle do
sha256 cellar: :any, high_sierra: "dcc9059b725fd7c87842287bbedf60a28745417652d42a300dcd944e15986f36"
sha256 cellar: :any, x86_64_linux: "cd94b6bc2189df7861c2c32c480f777984865dbab4107f493188feda5a05b80d"
end
pipenv shellの実行結果です。
設定まとめ
上で使用した環境変数を.bash_profileに設定しておくとbrewがそのまま動作するようになります。またPATHも張っておくと良いです。
export HOMEBREW_FORCE_BREWED_CURL=True
export HOMEBREW_FORCE_BREWED_GIT=True
export HOMEBREW_NO_ENV_FILTERING=True
export PATH=$HOME/opt/ssl/bin:$HOME/opt/curl/bin:$HOME/opt/git/bin:$PATH
export HOMEBREW_PATH=$HOME/opt/ssl/bin:$HOME/opt/bin:$HOME/opt/git/bin:$PATH
export LD_LIBRARY_PATH="$HOME/opt/ssl/lib:$HOME/opt/curl/lib:$LD_LIBRARY_PATH"
作業中のメモ書き、historyから起こした内容なので編集エラーがある場合コメントいただけますと幸いです。