LoginSignup
17
17

More than 5 years have passed since last update.

anyenv と direnv の併用

Last updated at Posted at 2015-01-17

背景

それぞれの特徴などは、別のページに譲る。

一例を上げますと。

Qiime と言うバイオのソフトウェアパッケージがありまして、これを自力でインストールするのは、中々の難物。
様々なバイオのコマンドをインストールしなければならないけど、

  • 個々のコマンドが、必ずしも最新版でない
  • 数々の環境変数を設定しなければならない
  • ヘタにインストールすると /usr/local/ を汚しまくる

って言う出来る事なら触りたくない代物。
更に言うなら、サーバーに新たに入れたいけど、

  • alternatives で切り替え? ちょっと無謀
  • 流石にサーバーに別途 bio linux は入れられない
  • 昔トラブって、 qiime-deloy はトラウマ。今は動くのか?

てな感じ。

上の例だけではなくて、

バイオのツールでは、細々としたコマンドだのスクリプトだのを放り込んでくるのは山程ある。

導入しようにも、色々と神経を磨り減らす。
コマンド名の競合が起こらないか、とか、今回インストールしたリストの管理は、とか、アンインストールは、とか。
更には、そのそれぞれが細かな環境変数を設定する様に指示して来たりして、あっと言うまに、 .*shrc がぐちゃぐちゃに。

当然の要望として、容易な(環境変数まで含め)環境切り替えツールが欲しくなる

環境切り替えの

代表格である virtualenvpyenv-virtualenv でコマンドの切り替えは行えるが、環境変数まで切り替えられるってのはなかなかない。逆に、direnv は、コマンドの管理部分は手付かず。

そこで、
  1. コマンドのインストール管理は、 pyenvanyenv
  2. 小規模なソフトウェアの検証などは、それ用の雑居環境を作り pyenv shell で、シェル上で環境変数を飛ばす形で。作業が終われば遮断される様に
    • python を要求しないものだとしても管理しやすくなる(?)
  3. 日常での大規模ソフトウェアパッケージ切り替えなどは、 direnv に任せる。
  4. web サーバー立てなきゃならんツール系は、今迄通り。

と言う単純なコンセプトの元、anyenv direnv のインストールと環境構築を行う事に。
以下、Qiime-1.8.0 の隔離環境を作る事を想定して、例に使う。

CentOS 6.6(一部 mac )

anyenv

  1. anyenv 本体のインストール
  2. pyenv, plenv, jenv のインストール

今の所、他の *env は実務で必要としていないので

まず、退避

$ mv .bashrc .bashrc~
$ mv .local .local.bak
  • .bashrc が汚いなら
  • ~/.local の方に $PYTHONPATH が読みに行ってトラブる。

過去の残滓で .local などの共通のライブラリパスにそれなりのモノが入ってるならば、整理整頓すべき

anyenv インストール

$ export PERL5OPT=   #<= 当方のみ必要
$ git clone https://github.com/riywo/anyenv ~/.anyenv
$ export PATH=${HOME}/.anyenv/bin:$PATH
$ eval "$(anyenv init -)"

pyenv インストール

$ anyenv install pyenv
$ git clone https://github.com/yyuu/pyenv-virtualenv.git ~/.anyenv/envs/pyenv/plugins/pyenv-virtualenv
$ eval "$(anyenv init -)"     # exec $SHELL -l 
$ pyenv install 2.7.3         # @mac: $ CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install 2.7.3
$ pyenv install 3.3.6
$ pyenv rehash
  • Qiime-1.8.0 で色々なインストールに使用する pip も自動的に入る

mac では、 python インストール時に

$ CFLAGS="-I$(xcrun --show-sdk-path)/usr/include" pyenv install 2.7.3 

しないと上手く行かない

pyenv-virtualenv

で、使用する隔離環境を作成
同じバージョンの python の環境を複数作る事が出来る

$ pyenv virtualenv 2.7.3 qiime
$ pyenv rehash
  • ソフトウェアパッケージ名など付ける
  • ${HOME}/.anyenv/envs/pyenv/versions/qiime に Qiime-1.8.0 で必要な python モジュールなどをインストールして行く

plenv インストール

plenv
$ anyenv install plenv
$ plenv install 5.20.1
$ plenv shell 5.20.1
$ plenv install-cpanm

cpanm は、個別にインストール

jenv インストール

jenv
$ anyenv install jenv
$ alternatives --config java

3 プログラムがあり 'java' を提供します。

  選択       コマンド
-----------------------------------------------
   1           /usr/lib/jvm/jre-1.5.0-gcj/bin/java
 + 2           /usr/lib/jvm/jre-1.6.0-openjdk.x86_64/bin/java
*  3           /usr/lib/jvm/jre-1.7.0-openjdk.x86_64/bin/java
$ jenv add /usr/lib/jvm/jre-1.5.0-gcj 
$ jenv add /usr/lib/jvm/jre-1.6.0-openjdk.x86_64
$ jenv add /usr/lib/jvm/jre-1.7.0-openjdk.x86_64
  • alternatives で管理されてるものの、、、
  • Qiime-1.8.0 での要求は、 1.6 系
  • system では 1.7

嵌った

'mac' で 'gnu screen' 使いで且つ、 'zsh' 使いの人が、anyenv を常用したいなら

% cd /etc               
% sudo mv zshenv zshenv.bak 
#% sudo mv zshenv zprofile 

しなきゃいけない

'CentOS' で 'gnu screen' 使いで且つ、 'zsh' 使いの人が、 anyenv を常用したいなら

% cd /etc
% sudo mv zshrc zshrc.bak

やら、しなきゃいけないのかも知れない(未検証)。

direnv

go インストール

無ければ

$ wget -q https://storage.googleapis.com/golang/go1.4.linux-386.tar.gz
$ tar zxf go1.4.linux-amd64.tar.gz 
$ mv go ../bin    # お好みの所
$ cd ../bin/go
$ export GOROOT=$PWD
$ cd go/bin
$ export PATH=$PWD:$PATH

GOROOT は設定してないと direnv コンパイル時にエラーする

direnv インストール

$ git clone https://github.com/zimbatm/direnv
$ cd direnv
$ make install DESTDIR=/PATH/TO/DIR  # お好みの所へ
$ eval "$(direnv hook bash)"

試す

$ cat /PATH/TO/.envrc
export FOOBAR=foobar
$ cd /PATH/TO
direnv: loading .envrc                                                                                                                                                                                                                    
direnv: export + FOOBAR

不満点

zsh でもプロンプトを変更して、

.envrc
export PROMPT='Qiime-1.8.0 $'

なんかしたい所だけど、プロンプトの中の変数やら解釈してくれないし、 / に移った時が悲惨。俺の環境だけだろうか
/.envrc なんか置きたくないし、、

運用

.bashrc に以下を記載

.bashrc
export PATH=${HOME}/.anyenv/bin:$PATH
eval "$(anyenv init -)"
eval "$(direnv hook bash)"

言うまでもなく、anyenv, direnv へのパスは通ってるものとする

インストール時

pyenv shell などで、そのシェルのみで明示的に有効にして、インストール

個別のコマンドは、

$ ./configure --prefix=${HOME}/.anyenv/envs/pyenv/versions/qiime

などで隔離を目指す

ちなみに

pyenv に関して pyenv rehash する事で、個別のコマンド(別記予定の、インストールした ghc など)も ${HOME}/.anyenv/envs/pyenv/shims に同期される

$ cat ${PYENV_ROOT}/pyenv/shims/ghc
#!/usr/bin/env bash
set -e
[ -n "$PYENV_DEBUG" ] && set -x

program="${0##*/}"
if [ "$program" = "python" ]; then
  for arg; do
    case "$arg" in
    -c* | -- ) break ;;
    */* )
      if [ -f "$arg" ]; then
        export PYENV_DIR="${arg%/*}"
        break
      fi
      ;;
    esac
  done
fi

export PYENV_ROOT="/PATH/TO/.anyenv/envs/pyenv"
exec "/PATH/TO/.anyenv/envs/pyenv/libexec/pyenv" exec "$program" "$@"
$ which ghc
~/.anyenv/envs/pyenv/shims/ghc
$ ghc --version
The Glorious Glasgow Haskell Compilation System, version 6.8.3
$ pyenv shell 3.3.6
$ ghc --version
pyenv: ghc: command not found

The `ghc' command exists in these Python versions:
  qiime

plenv でも同様だった。使うかどうかは別にして

コマンド使用時

direnv の機能を利用して

例えば、 Qiime-1.8.0 を使いたいディレクトリのみ

$ cat /PATH/TO/DIR/.envrc
export PYENV_VERSION=qiime
export JENV_VERSION=1.6.0.33
$ direnv allow

しておけば

$ pyenv versions
* system (set by PYENV_VERSION environment variable)
  2.7.3
  3.3.6
  qiime
$ jenv versions
* system (set by JENV_VERSION environment variable)
  1.5
  1.5.0
  1.6
  1.6.0.33
  1.7
  1.7.0.71
(略)

$ cd /PATH/TO/DIR
direnv: loading .envrc
direnv: export ~JENV_VERSION ~PYENV_VERSION
$ pyenv versions
  system
  2.7.3
  3.3.6
* qiime (set by PYENV_VERSION environment variable)
$ jenv versions
  system
  1.5
  1.5.0
  1.6
* 1.6.0.33 (set by JENV_VERSION environment variable)
  1.7
  1.7.0.71
(略)

と切り変わる

もちろん、子孫ディレクトリでも有効になったまま

外部コマンドに関しても、きちんと切り替わる。
ex) blastall

$ which blastall
/home/XXXX/.anyenv/envs/pyenv/shims/blastall
$ blastall | head -2 | tail -1
blastall 2.2.26   arguments:   # /usr/local/bin に入れたバージョン
$ cd /PATH/TO/DIR
direnv: loading .envrc
direnv: export ~JENV_VERSION ~PYENV_VERSION
$ which blastall
/home/XXXX/.anyenv/envs/pyenv/shims/blastall
$ blastall | head -2 | tail -1
blastall 2.2.22   arguments:   # 希望したバージョン
$ cd ../
$ direnv: unloading
$ blastall | head -2 | tail -1
blastall 2.2.26   arguments:

他の人

個人的に使う分には以上で良いが、サーバー上の他の人が使用したいケースが出てくる。
で、他の人が上の .bashrc をそのままコピーしたとしても anyenv は上手く動かない( direnv は単体としては正常動作)。
その"他の人"が、個人的に、anyenvdirenv をインストールして使えるレベルなら、まあ、勝手に対応するでしょうが、そうじゃない場合。

.bashrc
eval "$(anyenv init -)" 

を、そのまま埋め込む代りに、 eval "$(anyenv init -)" した結果を別途保存しておき、対象者の .bashrc 内で source する

そうすれば、期待通りの挙動になる。

17
17
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
17
17