Nix学習備忘録Part 1.5: direnvを導入する

2022-01-20T01:52:48Z

1 はじめに

direnvは、仮想環境使ってる人など、 導入するとかなり作業が快適になります。

Nix学習備忘録に入っていますが、 direnv自体はNixとは関係無く使えるので、 Nix興味無いって方もご一読頂けると幸いです。

Nixでの利用方法は(大した分量ではありませんが)、 終盤に持ってきています。 Nixでの利用例は前回の記事 で作った~/work/png2pdfプロジェクトで動作確認をしますが、 読んでいなくても、それまでの内容で何となく何ができているのかはお分かり頂けるかと思います。

また、direnvの使用をオススメはしますが、 今後Nixを使う上で必須というわけではないので、 必要無いと思った人は導入しなくても構いません。

2 direnvとは

CUI上で環境変数を切り替えることができるツールで、 ディレクトリごとに環境を作った際、そのディレクトリに 入ったタイミングで環境変数を追加出たタイミングで環境変数を削除することができます。

3 direnvのインストール方法

今回も何番煎じになるのかわかりませんが、 インストール方法を記載します。

他のサイトでは、エディタの指定をして、 direnv editというコマンドで設定を書くようにしていますが、 直接編集することもできるので、私はエディタの設定はしていません1

4 direnvの使用方法

4.1 状況設定

まず、適当な作業用ディレクトリを作ります。

$ cd ~
$ mkdir direnv_example && cd $_

環境変数が削除されるのも確認したいので、 グローバルに環境変数HOGE=hogeを追記します。

※ 後で削除する設定なので、書いたり消したりするのが面倒な方は、 「HOGE=hogeって環境変数を作って、 後でこれが自動で削除されるのを確認する」 程度を頭に入れて、適当に読み飛ばしてください。

ここではbashで説明します。zshの場合はbashをすべてzshで読み替えて読んでください。

# グローバル環境変数HOGEを.bashrcに記述
$ echo "export HOGE=hoge" >> ~/.bashrc
# .bashrcに記述されたことを確認
$ cat ~/.bashrc | grep "HOGE"
expoert HOGE=hoge
# .bashrcを読み込んでいないので、まだ設定はされていない
$ echo $HOGE
# .bashrcを再読み込み
$ source ~/.bashrc
# 環境変数HOGEが使えるようになったことを確認
$ echo $HOGE
hoge

4.2 初期設定

direnvの使用方法は至って簡単です。 環境変数を記述した.envrcというファイルを、 プロジェクトのルート置きます。 追加したい環境変数を.bashrc.zshrcに記述するときと同様、 exportで記述し、削除したい環境変数をunsetで記述します。

export FUGA=fuga
unset HOGE

保存すると、ターミナルに以下のような出力がされます:

direnv: error /home/username/direnv_example/.envrc is blocked. Run `direnv allow` to approve its content

direnvが.envrcを評価しようとしたら、 ブロックされたから、direnv allowで許可してと言っています。

許可する前に、今の環境変数を確認しましょう。 HOGEはグローバル環境変数として記述しており、 FUGAは評価してない.envrc内に入っているので、 それぞれ評価すると次のようになります:

# 現在direnv_exampleにいることを確認
$ pwd
/home/username/direnv_example
# グローバル環境変数なので出力される
$ echo $HOGE
hoge
# まだ評価してない.envrcに記述しているため何も出力されない
$ echo $FUGA

$

それでは、direnvに.envrcの評価を許可しましょう。

$ direnv allow
direnv: loading ~/direnv_example/.envrc
direnv: export +FUGA -HOGE

既にexport +FUGA -HOGEと書かれています。 実際にグローバルで定義した環境変数HOGEが削除され、 .envrcで追加させたFUGAが追加されていることを確認しましょう。

# グローバルで定義したHOGEは削除されたので、何も出力されない
$ echo $HOGE

# .envrcで追加したので、FUGAは出力される
$ echo $FUGA
fuga

4.3 動作確認

direnvはディレクトリごとに自動で環境を有効/無効にできます。 direnv_example.envrcに記述した内容は、 ディレクトリに出入りするだけで有効/無効にできます。

実際見てみましょう。

# 現在の位置を確認
$ pwd
/home/username/direnv_example
$ echo $HOGE

$ echo $FUGA
fuga
# 親ディレクトリに移動
$ cd ..
direnv: unloading
$ echo $HOGE
hoge
$ echo $FUGA

# 再度direnv_exampleへ移動
$ cd direnv_example
direnv: loading ~/direnv_example/.envrc
direnv: export +FUGA -HOGE
$ echo $HOGE

$ echo $FUGA
fuga

ちゃんと、direnv_exampleに入ったら.envrcが評価され、 direnv_exampleから抜けたら元の環境に戻っていることがわかります。

direnvの動作確認自体はこれで終わりなので、 .bashrc.zshrcに記述したexport HOGE=hogeは 消しておいてください。

4.4 余談: Pythonとvirtualenvの組み合わせでの使用例

Pythonユーザー以外には関係無いのと、 virtualenv使いこなしてる人には細かい説明は要らないと思うので簡単な説明に留めますが、 .envrcに以下のように記述しておけば、 仮想環境がディレクトリ移動で勝手に切り替わってくれるので、 deactivateし忘れる心配が無くなります。

※ 仮想環境のディレクトリ名は.venvとしています。

source .venv/bin/activate

5 Nixでdirenvを使用する

本題です。本題なんですが、話はすぐ終わります。

.envrcに記述する内容は次の一行だけです:

use nix

終わりです。お疲れ様でした。

。。。

。。。一応、前回作った~/work/png2pdfに、 上の内容の.envrcを記述してみます。 前節の例と同様、許可を求められるので、direnv allowで許可します。

$ pwd
/home/username/work/png2pdf
$ echo "use nix" > .envrc
direnv: error /home/username/work/png2pdf/.envrc is blocked. Run `direnv allow` to approve its content
$ direnv allow
direnv: loading ~/work/png2pdf/.envrc
direnv: using nix
direnv: using cached derivation
direnv: eval /username/work/png2pdf/.direnv/cache-pre346058.bc59ba15b64
direnv: export +AR +AS +CC +CONFIG_SHELL +CXX +DETERMINISTIC_BUILD+HOST_PATH +IN_NIX_SHELL +LD +NIX_BINTOOLS +NIX_BINTOOLS_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_BUILD_CORES +NIX_BUILD_TOP +NIX_CC +NIX_CC_WRAPPER_TARGET_HOST_x86_64_unknown_linux_gnu +NIX_CFLAGS_COMPILE +NIX_ENFORCE_NO_NATIVE +NIX_HARDENING_ENABLE +NIX_INDENT_MAKE +NIX_LDFLAGS +NIX_STORE +NM +OBJCOPY +OBJDUMP +PYTHONHASHSEED +PYTHONNOUSERSITE +PYTHONPATH +RANLIB +READELF +SIZE +SOURCE_DATE_EPOCH +STRINGS +STRIP +TEMP +TEMPDIR +TMP +XDG_DATA_DIRS +_PYTHON_HOST_PLATFORM +_PYTHON_SYSCONFIGDATA_NAME +__ETC_PROFILE_SOURCED +buildInputs +buildPhase +builder +configureFlags +depsBuildBuild +depsBuildBuildPropagated +depsBuildTarget +depsBuildTargetPropagated +depsHostHost +depsHostHostPropagated +depsTargetTarget +depsTargetTargetPropagated +doCheck +doInstallCheck +name +nativeBuildInputs +out +outputs +patches +phases +propagatedBuildInputs +propagatedNativeBuildInputs +shell +shellHook +stdenv +strictDeps +system ~PATH
$

大量の環境変数が読み込まれていることがわかります。 Pythonとimg2pdfが使えるかどうか確認してみましょう。

$ pwd
/home/username/work/png2pdf
$ python
Python 3.9.9 (main, Nov 15 2021, 18:05:17)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import img2pdf
>>> img2pdf.__version__
'0.4.3'
>>>

無事使えています。 ディレクトリを出て、pythonが使えなくなることを確認し、 再度入り直して、また使えるようになることを確認しましょう。

>>> exit()
$ cd ..
direnv unloading
$ python
python: command not found
$ cd png2pdf
direnv: loading ~/work/png2pdf/.envrc
direnv: using nix
(以下略)
$ python
Python 3.9.9 (main, Nov 15 2021, 18:05:17)
[GCC 10.3.0] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> import img2pdf
>>> img2pdf.__version__
'0.4.3'
>>>

これで毎度毎度nix-shellを実行しなくても、 ディレクトリに入るだけでimg2pdfが使えるPythonの環境に入ることができ、 ディレクトリを抜けるだけでクリーンな環境に戻ることができるようになりました。

6 まとめ

direnvを使うことで、構築した環境に自動で出入りすることができるようになりました。

次回の内容は未定ですが、

  • PoetryとNixを用いてより優れた環境を構築する
  • Nixで再構成が容易なユーザー環境を構築する

のいずれかの方針で進めて行こうかと思います。

もしかすると、行ったり来たりするかもしれませんが、 備忘録なので悪しからず。。。


  1. もしかしたら、Nix以外でdirenvを利用する場合に、 何か不都合が生じるのかもしれません。気になる方は、 他の記事同様、~/.bashrc~/.zshrcexport EDITOR=<エディタ名>と記述してください。↩︎