modalsoul’s blog

これは“失敗”と呼べるかもしれないが、ぼくは“学習体験”と呼びたい

direnvで.envrcに設定した環境変数が読み込まれない場合

tl;dr

  • シェル設定ファイルのdirenv hookの設定を確認
    • ex). .bashrc.zshrcを確認

事象

  • direnvをインストール
  • .envrcファイルを作成
  • .envrcファイルに環境変数を記述
  • 設定した環境変数が読み込まれない
  • direnv allow しても同様に読み込まれない

原因

シェル設定ファイルにhookする設定の追加が漏れていた。

解決方法

手元の環境はzshなので、.zshrcにeval "$(direnv hook zsh)"を追加することで、direnvが正常に機能するようになった。

詳解

direnv hookはdirenvをシェルに統合するためのコマンドで、各shに対する初期化スクリプトのコードを出力する。このコードが実行されることで、direnvが自動的に動作し、環境変数のロード・アンロードを行う。

zshの場合のdirenv hookの出力

_direnv_hook() {
  trap -- '' SIGINT
  eval "$("/Users/hoge/.asdf/installs/direnv/2.34.0/bin/direnv" export zsh)"
  trap - SIGINT
}
typeset -ag precmd_functions
if (( ! ${precmd_functions[(I)_direnv_hook]} )); then
  precmd_functions=(_direnv_hook $precmd_functions)
fi
typeset -ag chpwd_functions
if (( ! ${chpwd_functions[(I)_direnv_hook]} )); then
  chpwd_functions=(_direnv_hook $chpwd_functions)
fi

_direnv_hook関数

direnvを呼び出し、環境変数を更新する。

1行目のtrapでSIGINTを無視し、処理中に中断されないようにしている。 direnv export zsh.envrcを読み込み、3行目のtrapでSIGINTに対する処理をデフォルトに戻している。

precmd_functions

precmd_functions_direnv_hookが含まれない場合、precmd_functionsに追加。 こうすることで、プロンプトが表示される直前に_direnv_hookが実行される。

chpwd_functions

chpwd_functions_direnv_hookが含まれない場合、chpwd_functionsに追加。 こうすることで、カレントディレクトリが変更された場合に_direnv_hookが実行される。