Nix学習備忘録Part 1.5: direnvを導入する
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で再構成が容易なユーザー環境を構築する
のいずれかの方針で進めて行こうかと思います。
もしかすると、行ったり来たりするかもしれませんが、 備忘録なので悪しからず。。。
もしかしたら、Nix以外でdirenvを利用する場合に、 何か不都合が生じるのかもしれません。気になる方は、 他の記事同様、
~/.bashrc
や~/.zshrc
にexport EDITOR=<エディタ名>
と記述してください。↩︎