direnv

DIRENV 1 “2019” direnv “取扱説明書”

名称

direnv - .profileを散らかさない

処方

direnv コマンド

解説

direnvはシェルの環境変数の管理器です。 現在のディレクトリによって、環境変数を読み込んだり読み戻したりするために、bashやzshやfishといったシェルにフックを掛けられます。 これにより、プロジェクト固有の環境変数を持たせることができ、「~/.profile」ファイルが散らかりません。

各プロンプトの前に、現在のディレクトリとその上位のディレクトリの.envrcファイルの存在がdirenvにより確認されます。 ファイルが存在するとき、bashの副シェルに読み込まれ、全てのエクスポートされた変数がdirenvに捕捉されて、現在のシェルで使えるようになります。 また、設定が外れた変数は削除されます。

direnvは単一の静的実行ファイルにコンパイルされるため、プロンプトが表示されるとき、存在を感じさせない程度には高速です。 また言語に依らないため、rbenv、pyenv、phpenv等に似たソリューションの構築に使えます。

$ cd ~/my_project
$ echo ${FOO-nope}
nope
$ echo export FOO=foo > .envrc
\.envrc is not allowed
$ direnv allow .
direnv: reloading
direnv: loading .envrc
direnv export: +FOO
$ echo ${FOO-nope}
foo
$ cd ..
direnv: unloading
direnv export: ~PATH
$ echo ${FOO-nope}
nope

準備

direnvが適切に機能するためには、シェルにフックする必要があります。 それぞれのシェルには、独自の拡張の仕組みがあります。

BASH

以下の行を~/.bashrcファイルの末尾に加えてください。

eval "$(direnv hook bash)"

必ず、rvm、git-promptやその他のプロンプトを操作するシェルの拡張より後にくるようにしてください。

ZSH

以下の行を~/.zshrcファイルの末尾に加えてください。

eval "$(direnv hook zsh)"

FISH

以下の行を$XDG_CONFIG_HOME/fish/config.fishファイルの末尾に加えてください。

direnv hook fish | source

Fishは3つのモードに対応しており、大域環境変数direnv_fish_modeで設定できます。

set -g direnv_fish_mode eval_on_arrow    # プロンプト、及び矢印ベースのディレクトリの変更でdirenvを開始(既定)
set -g direnv_fish_mode eval_after_arrow # プロンプト、及び実行コマンド前の矢印ベースのディレクトリの変更でのみdirenvを開始
set -g direnv_fish_mode disable_arrow    # プロンプトでのみdirenvを開始。元々の動作と似た機能性です

TCSH

以下の行を~/.cshrcファイルの末尾に加えてください。

eval `direnv hook tcsh`

Elvish

以下を実行してください。

~> mkdir -p ~/.config/elvish/lib
~> direnv hook elvish > ~/.config/elvish/lib/direnv.elv

そして、以下の行を~/.config/elvish/rc.elvファイルに加えてください。

use direnv

PowerShell

以下の行を$PROFILEに加えてください。

Invoke-Expression "$(direnv hook pwsh)"

Murex

以下の行を~/.murex_profileに加えてください。

direnv hook murex -> source

コマンド

direnv allow [rcへのパス] : 与えられた.envrcや.envファイルを読み込むことを許可します。

direnv deny [rcへのパス] : 与えられた.envrcや.envファイルの認可を失効させます。

direnv edit [rcへのパス] : rcへのパス、または現地点にある.envrc、ないし.envを$EDITORで開き、その後でファイルを読み込めるようにします。

direnv exec ディレクトリ コマンド [...引数] : ディレクトリで最初に見つかった.envrcないし.envを読み込んだ後でコマンドを実行します。

direnv export シェル : .envrcないし.envを読み込み、エクスポートで使える差分を印字します。対応しているシェルは、bash, zsh, fish, tcsh, elvish, pwsh, murex, json, vim, gha (GitHub Actions), gzenv, systemdです。

direnv fetchurl <url> [<整合性ハッシュ>] : 与えられたURLをdirenvのCASに取得します。

direnv help : このヘルプを表示します。

direnv hook シェル : シェルのフックを立ち上げるのに使います。

direnv prune : 許可されたファイルのうち古いものを削除します。

direnv reload : envの再読み込みを開始します。

direnv status : デバッグ状態の情報を印字します。

direnv stdlib : .envrcの実行の文脈で使える標準ライブラリを表示します。

direnv version : バージョンを印字するか、VERSION_AT_LEASTよりdirenvが古いかどうかを判定します。

使い方

対象のフォルダにより、.envrcファイルを作ってexport(1)やunset(1)ディレクティブを加えてください。

次のプロンプトを見ると、.envrcが阻まれたことでdirenvが文句を言っていることに気付きます。 これは安全のための仕組みであり、自動で新しいファイルを読み込むのを避けています。 さもなくば、プルした全てのgitリポジトリや、開封したtarアーカイブにより、その中にcdしたが最後、ハードドライブを消し去ってしまうことができるでしょうから。

ここでは何も悪いことは起きようがないことは確実です。 direnv allow .と入力し、direnvが新しい環境を読み込む様子を見てください。 なお、.direnv edit .は手軽なショートカットであり、$EDITORでファイルを開いてファイルの変更時間が変化したときに自動で再読込されます。

これで環境が読み込まれました。 ディレクトリの外にcdすると、自動で読み戻されることに気付かれるでしょう。 cdで中に戻ると、再び読み込まれます。 以上が基本的な仕組みであり、これを使うと色々と工夫できるでしょう。

手作業で変数をエクスポートするのは、ちょっとした作業の繰り返しになってしまいます。 そこでdirenvでは、いろいろな補助関数が提供されており、.envrcファイルの文脈で使えるようになっています。 詳しくはdirenv-stdlib(1)のmanページをご確認ください。 また、$XDG_CONFIG_HOME/direnv/direnvrcないし$XDG_CONFIG_HOME/direnv/lib/*.shファイルの中に、独自の拡張を定義することもできます。

きっとここまでで始めてみる分には充分でしょう。

環境

XDG_CONFIG_HOME:既定で$HOME/.configです。

XDG_DATA_HOME:既定で$HOME/.local/shareです。

ファイル

$XDG_CONFIG_HOME/direnv/direnv.toml:Direnvの構成です。direnv.toml(1)を参照。

$XDG_CONFIG_HOME/direnv/direnvrc.envrcの前に、毎回読み込まれるBashコードです。個人用の拡張に好適です。

$XDG_CONFIG_HOME/direnv/lib/*.sh.envrcの前に毎回読み込まれるBashのコードです。サードパーティの拡張に好適です。

$XDG_DATA_HOME/direnv/allow:どの.envrcファイルがdirenv allowされたかを記録しているところです。

貢献

不具合の報告、貢献、フォークを歓迎します。

不具合やその他の議論は全て、 http://github.com/direnv/direnv/issues でされています

ウィキもあり、使用しているパターン、その他のコツやトリックを共有したりすることができます:https://github.com/direnv/direnv/wiki

もしくは、チャットをされる方はFreeNodeの#direnvチャンネルにお立ち寄りください。

著作情報

MIT licence - Copyright (C) 2019 @zimbatm and contributors

こちらも参照

direnv-stdlib(1), direnv.toml(1), direnv-fetchurl(1)