anyenv と direnv の併用


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

##### 一例を上げますと。
[Qiime](http://qiime.org/) と言うバイオのソフトウェアパッケージがありまして、これを自力でインストールするのは、中々の難物。
様々なバイオのコマンドをインストールしなければならないけど、

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

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

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

てな感じ。

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

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

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

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

##### そこで、

1. コマンドのインストール管理は、 `pyenv`（`anyenv`）
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` は実務で必要としていないので

### まず、退避

```bash:
$ mv .bashrc .bashrc~
$ mv .local .local.bak
```

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



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


### anyenv インストール

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

### pyenv インストール
```bash:
$ 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` インストール時に

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

しないと上手く行かない

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

```bash:
$ pyenv virtualenv 2.7.3 qiime
$ pyenv rehash
```

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




### plenv インストール

```bash:plenv
$ anyenv install plenv
$ plenv install 5.20.1
$ plenv shell 5.20.1
$ plenv install-cpanm
```
`cpanm` は、個別にインストール

### jenv インストール

```bash: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` を常用したいなら

```bash:
% cd /etc               
% sudo mv zshenv zshenv.bak 
#% sudo mv zshenv zprofile 
```
しなきゃいけない

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

```bash:
% cd /etc
% sudo mv zshrc zshrc.bak
```
やら、しなきゃいけないのかも知れない（未検証）。

## direnv

### go インストール
無ければ

```bash:
$ 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 インストール
```bash:
$ git clone https://github.com/zimbatm/direnv
$ cd direnv
$ make install DESTDIR=/PATH/TO/DIR  # お好みの所へ
$ eval "$(direnv hook bash)"
```


### 試す
```bash:
$ cat /PATH/TO/.envrc
export FOOBAR=foobar
$ cd /PATH/TO
direnv: loading .envrc                                                                                                                                                                                                                    
direnv: export + FOOBAR
```


#### 不満点

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

```bash:.envrc
export PROMPT='Qiime-1.8.0 $'
```

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



### 運用

`.bashrc` に以下を記載

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

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

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

個別のコマンドは、

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

などで隔離を目指す

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

```bash:
$ 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 を使いたいディレクトリのみ

```bash:
$ cat /PATH/TO/DIR/.envrc
export PYENV_VERSION=qiime
export JENV_VERSION=1.6.0.33
$ direnv allow
```
しておけば

```bash:
$ 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
（略)
```
が

```bash:
$ 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

```bash:
$ 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` は単体としては正常動作）。
その"他の人"が、個人的に、`anyenv` や `direnv` をインストールして使えるレベルなら、まあ、勝手に対応するでしょうが、そうじゃない場合。

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

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