Environment modules のインストールと *modulefile* の登録


本稿では，[Environment Modules](http://modules.sourceforge.net/)をインストールし，MPICHをモジュールとして登録します．
クラスタ環境などにおいて`module`コマンドを扱ったことがあると理解しやすいと思います．

### 環境

- CentOS 6.5

## Environment Modules のインストール

インストールは`yum`で行います．

```terminal
sudo yum install environment-modules
```

一旦ログアウトしてログインし直すと，`module`コマンドが使えるようになっていると思います．

## *modulefile* の配置

各モジュールは *modulefile* と呼ばれるTclスクリプトによって管理されています．
`module`コマンドは *modulecmd* のエイリアス?となっていて，実行の実態は *modulecmd* のようです．

### *modulefile* を配置するフォルダの設定

*modulecmd* は，環境変数 **MODULEPATH** に記載されているディレクトリ以下から再帰的に *modulefile* を検索します．
ユーザログイン時に設定されるシステム内共有の **MODULEPATH** を変更するには，`/usr/share/Modules/init/.modulepath`(CentOS6.5の場合)を書き換えます．
今回は，`/modules`以下に *modulefile* を設置していくことにしたので，`/usr/share/Modules/init/.modulepath`の末尾に以下の行を追加します．

```/usr/share/Modules/init/.modulepath
/modules
```

必要であれば，現在設定されているパスもコメントアウトします．
編集が終わったら，再ログインします．
(再ログインした時点で，`.modulepath`の設定が反映されます)

設置するディレクトリを作ってない場合は，作っておきましょう．

```terminal
sudo mkdir /modules
```

### (必要となるコンパイラ，ライブラリのインストール)

コンパイラや，MPIなどをインストールします．
インストール手順については，本稿では省きますが，可能な限りソースからビルドした方が良いと思います．
(`yum`などでインストールすると， *modulefile* の設置などを自動で行ってくれたりするのでしょうか…？)

### *modulefile* の作成

各 *modulefile* を作成します．
今，`/modules/hoge/ver_suffix`という *modulefile* を作成すると，

```terminal
module avail
```

で出てくるモジュールリストの中に **hoge/ver_suffix** が出てきます．
ユーザは，

```terminal
module load hoge/ver_suffix
```

とすることで，`/modules/hoge/ver_suffix`の中に書かれた内容が *modulecmd* によって解釈され，シェルに適用されます．

*modulefile* の名前は自由につけることが可能ですが，解りやすい名前を付けましょう．

---

以下では，MPICH 3.1 を GCC 4.4.7 (CentOS 6.5 default)向けにコンパイルしたものについての *modulefile* を作ります．
以下のソースを，`/modules/mpich/3.1_gcc-4.4.7`という名前で作成します．

```/modules/mpich/3.1_gcc-4.4.7
#%Module1.0
##
## MPICH 3.1 for GCC 4.4.7 (system default)
proc ModulesHelp { } {
        puts stderr "MPICH 3.1 for GCC 4.4.7\n"
}

module-whatis   "MPICH 3.1 for GCC 4.4.7"

# for Tcl script only
set     mpi_path        /usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7

# append pathes
prepend-path    CPATH           $mpi_path/include
prepend-path    PATH            $mpi_path/bin
prepend-path    LD_LIBRARY_PATH $mpi_path/lib
prepend-path    LD_RUN_PATH     $mpi_path/lib
prepend-path    MANPATH         $mpi_path/share/man
```

- 先頭の`#%Module1.0`は，このファイルが *modulefile* であることを示す
- **mpi_path** は実際にMPICHをインストールしたディレクトリ(今回は，`/usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7`にインストールした)
- `proc ModulesHelp`の中身は， `module help modulename`で実行される
- `prepend-path VARIABLE VALUE` は， **VALUE** を環境変数 **VARIABLE** の前に追記する
 - `append-path` を用いると，前ではなく後に追記することができる
- より詳しくは，Reference先を参照のこと

作成したら，

```terminal
module avail
```

で出てくるか確認します．
大体以下の様な出力が得られるはずです．

```terminal
--------------------------------------------- /modules ---------------------------------------------
mpich/3.1-gcc-4.4.7
```

実際に適用できているか確認してみましょう．
大体以下の様な出力になると思います．

```terminal
[21:24:58,****@****:~]$ module list
No Modulefiles Currently Loaded.
[21:25:03,****@****:~]$ export > env_1
[21:25:10,****@****:~]$ module load mpich/3.1-gcc-4.4.7
[21:25:32,****@****:~]$ module list
Currently Loaded Modulefiles:
  1) mpich/3.1-gcc-4.4.7
[21:25:37,****@****:~]$ export > env_2
[21:25:49,****@****:~]$ module unload mpich/3.1-gcc-4.4.7
[21:25:54,****@****:~]$ module list
No Modulefiles Currently Loaded.
[21:25:59,****@****:~]$ export > env_3
[21:26:08,****@****:~]$ diff env_1 env_2
1a2
> declare -x CPATH="/usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7/include"
11c12,13
< declare -x LD_LIBRARY_PATH="/home/****/local/lib"
---
> declare -x LD_LIBRARY_PATH="/usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7/lib:/home/****/local/lib"
> declare -x LD_RUN_PATH="/usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7/lib"
13a16
> declare -x LOADEDMODULES="mpich/3.1-gcc-4.4.7"
19c22
< declare -x MANPATH="/usr/share/man"
---
> declare -x MANPATH="/usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7/share/man:/usr/share/man"
23c26
< declare -x PATH="/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/home/****/bin"
---
> declare -x PATH="/usr/local/mpi/mpich/mpich-3.1_gcc-4.4.7/bin:/usr/lib64/qt-3.3/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/home/****/bin"
39a43
> declare -x _LMFILES_="/modules/mpich/3.1-gcc-4.4.7"
[21:27:19,****@****:~]$ diff env_1 env_3
```

- **LOADEDMODULES** は現在読み込まれているモジュール
- **\_LMFILES\_** は現在読み込まれているモジュールの *modulefile*

*env_1* (何もロードする前)と *env_2* (ロード後)をdiffすると， *modulefile* に書いた内容と，上記2点が反映されていることが分かります．
`module unload`すると，何もロードする前と同じになっていることが分かります．
(*env_1* と *env_3* のdiff)

## ユーザ毎のModulefileを設置する

各ユーザはログインスクリプト(ex. `~/.bash_profile`)等で環境変数 **MODULEPATH** を上書きすることにより，ユーザ独自の *modulefile* を認識させることが可能になる．

つまり，システム共通で使用する *modulefile* と分離させることが可能．

## Reference

- [Man Page of MODULE](http://modules.sourceforge.net/man/module.html)
- [Man Page of MODULEFILE](http://modules.sourceforge.net/man/modulefile.html)