pyてよn日記

一寸先は闇が人生

direnv の使い方

開発環境に direnv を導入してみたので使い方を簡単にまとめた.

direnv とは

ディレクトリ毎の環境変数の設定を行うことができるようになる CLI ツール.

ディレクトリ毎に環境変数を定義して,そのディレクトリがカレントディレクトリになったときだけ環境変数を有効 / 無効にしてくれるソフトウェア.プロジェクト毎,開発中のアプリ毎に環境変数を変えたい時に重宝する.

筆者の開発環境

インストール

$ brew install direnv
  • シェルに hook を追加する(direnv を動作させるための設定)
    • ~/.zshrc に以下の 2 行を追加.追加したらシェルを再起動(それぞれのシェッルに置き換えてください)
    • EDITOR には,シェルでエディタを起動させる際のコマンドを代入する(codeviemacs など.筆者は code を選択.)
export EDITOR=code
eval "$(direnv hook zsh)"

基本的な使い方

以下の手順を踏めば,ディレクトリ毎に環境変数を設定できるようになる.

  • プロジェクトディレクトリを作成して移動
  • direnv edit . を実行
  • EDITOR に設定したエディタで .envrc というファイルが開かれる(初回実行時は .envrc が自動生成される.次回以降は既存の .envrc が開かれる)
  • そのディレクトリで有効にしたい環境変数などの設定を .envrc に記述
    • (要ソース).envrcbash で評価されることに注意.自分の環境では .envrc が読み込まれとき echo $SHELL を実行したら /bin/zsh が出力されたけどどうなんだろう.

デモ 1:基本的な使い方

$ mkdir my-project
$ direnv edit .
  • my-project/.envrc
echo '===== .envrc loading ===='

export FOO='FOOBARBUZ'
echo "$SHELL"

# 上位ディレクトリで設定された環境変数を消去(unset)する
unset ABC

echo '===== .envrc loaded ===='
# `.envrc` が置かれたディレクトリに移動
$ cd my-project
direnv: loading ~/my-project/.envrc
===== .envrc loading ====
/bin/zsh
===== .envrc loaded ====
direnv: export +FOO

$ echo $FOO
FOOBARBUZ

# 上位のディレクトリに移動し,.envrc を無効化
$ cd ../
direnv: unloading  # unload したという出力が行われる
$ echo $FOO
# 何も出力されない

エラー処理:direnv が実行できない時

以下のように,ディレクトリを移動した時に direnv が実行できないというエラーが発生する場合がある.

$ cd my-project
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.

上記出力にあるように,以下のコマンドを実行すれば OK.

$ direnv allow
direnv: loading ~/my-project/.envrc
===== .envrc loading ====
/bin/zsh
===== .envrc loaded ====
direnv: export +FOO

デモ 2:Python の venv と組み合わせる

direnv を Python の venv と組み合わせると,プロジェクトディレクトリへ移動したときに仮想環境を activate とすることができ,そのディレクトリを抜けると自動で deactivate される(これ,Python 使いの人だと結構使っている方がいるかもしれない.使っていないかたは便利なので是非!).

上記を以下のような手順で実現する.

  1. Python の仮想環境を作る
  2. .envrc に仮想環境を activate するコマンドを記述
  3. プロジェクトディレクトリに移動(仮想環境が activate)
  4. プロジェクトディレクトリを抜ける(仮想環境が deactivate)

仮想環境を作る.

$ cd my-project
$ python -m venv venv

プロジェクトディレクトリ配下に,以下のような .envrc を作成

source venv/bin/activate

# 環境変数
export PYTHONPATH=${APP_HOME}
export FOO='FOO'
export BAR='BAR'

シェルを再起動し(これいらないかも),そのディレクトリに移動する.

$ cd my-project
direnv: loading ~/Projects/my-project/.envrc
direnv: export +BAR +FOO ~PYTHONPATH
(venv)$ python  # 仮想環境 activate
>>> ...

ディレクトリを抜ける.

(venv)$ cd ../
direnv: unloading
$ ...  # 仮想環境 deactivate

注意点:alias と関数は読み込まれない

(蛇足なので興味ある人だけ)

direnv を用いてディレクトリ毎のコマンド(alias と関数)を設定しようとしたら読み込んでくれなかった(そもそも読み込まれないらしい.ソースコード見てないので詳細は分からん).もし,どうしてもディレクトリ毎のコマンドを設定したい場合は以下の記事,issue を参考にすると良い.

eidera.com

github.com

設定方法は少しめんどくさく,力技で解決しているという感じ.上記のリンクの手順を以下に要約した(上記リンク読まないと解読できないかも).弄る必要があるファイルは .direnvrc(direnv が起動時に読み込まれる設定ファイル),.envrc の 2 つ.

  1. .direnvrc というファイルをホームディレクトリに作成
  2. .direnvrc に,「定義した関数(登録したいコマンド)を実行権限付きファイルとして吐き出す」という関数を定義する.吐き出されるディレクトリは ALIASES_DIR という変数に定義しておく.
  3. .envrc 内で登録したいコマンドを「関数として」(alias ではだめ)定義し,手順 2 で定義した関数に,「登録したい関数の関数名」を渡す.
  4. そのディレクトリに移動すると,ALIASES_DIR に定義したディレクトリ配下に,自分が登録した関数名の実行権限付きファイルが吐き出される.そしてディレクトリを PATH に追加し,(ちなみに,この吐き出されたファイルはそのディレクトリから抜けても残り続ける.再度そのディレクトリへ移動したときに消去 & 再度作成されるため,変更はちゃんと反映されるようになっている).

要は alias,関数を使えるようにするのではなく,「実行権限を持ったファイルを自動生成し,そのファイルが保存されたディレクトリを PATH に追加し使えるようにしている」のである.シェルのビルトインコマンドと同じようなことをやっている訳です.

ディレクトリ毎に alias と関数を読み込んでコマンドとして使えるようになって欲しい(プルリク出すぞってほどの気概はないです...).

終わりに

direnv はいいぞ.

あと,alias と関数を .envrc から上手く読み込む方法を知ってる方いたらコメントしていただけると幸いです!

いずれ読みたい

blog.p1ass.com