AWS とかを頻繁に弄るようになってきた今、direnv 無しでは生きられない体になってきました。
が、いままで漠然と使ってきていたので direnv について改めて調べました。
インストール
下記から適当なバイナリをダウンロードし、パスの通ったところに保存して実行属性を付けます。
またはソースからビルドします。
git clone https://github.com/direnv/direnv
cd direnv
make install
あるいは go get
でも大丈夫だと思います(ビルドできる環境があるなら)。
go get github.com/direnv/direnv
インストールできたら Bash のシェルのフックを設定します。
vim ~/.bashrc
次のように追記します。
# ~/.bashrc
eval "$(direnv hook bash)"
反映します。
exec bash --login
使ってみる
適当なディレクトリで direnv edit .
するとエディタが起動します。
direnv edit .
以下のように環境変数のエクスポートを記述します。
export AWS_DEFAULT_PROFILE=oreore
export AWS_PROFILE=$AWS_DEFAULT_PROFILE
エディタを終了すると次のように表示されます。
direnv: loading .envrc
direnv: export +AWS_DEFAULT_PROFILE +AWS_PROFILE
env で環境変数を確認してみると、設定されていることがわかります。
env | grep ^AWS
#=> AWS_PROFILE=oreore
#=> AWS_DEFAULT_PROFILE=oreore
別のディレクトリに移動します。
cd ../other
すると次のように表示されます。
direnv: unloading
環境変数がクリアされています。
env | grep ^AWS
#=>
direnv: error .envrc is blocked. Run direnv allow
to approve its content.
direnv edit
で編集されるファイルはカレントディレクトリの .envrc
なので直接編集することも可能です。
vim .envrc
編集すると次の警告が表示されます。
direnv: error .envrc is blocked. Run `direnv allow` to approve its content.
安全のために、.envrc
が変更された後は direnv allow
するまで無効になっています。
例えば、誰かが /tmp/.envrc
を rm -fr /
みたいな内容で作成した状況を想像してみてください。
direnv allow
すると有効になります。
direnv allow
direnv edit
で編集した場合は自動的に direnv allow
されるので、direnv allow
する必要はありません。
direnv allow
の情報は ~/.config/direnv/allow/
に保存されています。
ll ~/.config/direnv/allow/
#=> -rw-r--r-- 1 ngyuki staff 0 10 22 01:22 221e5718...
#=> -rw-r--r-- 1 ngyuki staff 0 10 22 01:15 6d84e3c8...
#=> -rw-r--r-- 1 ngyuki staff 0 10 22 01:23 dc9609ff...
sha256 っぽいファイルが沢山作成されています。ファイル名+内容を sha256 したもののようです。
{ realpath .envrc; cat .envrc; } | sha256sum
詳細は以下のとおりです。
stdlib
.envrc
ファイルの中ではいくつか便利なユーティリティ関数が使えます。特に使いそうなやつを説明します。
expand_path
expand_path <rel_path> [relative_to]
- 指定された相対パスを絶対パスに変換して出力します
- 2番目の引数が基準となるディレクトリです
- 省略するとカレントディレクトリが基準になります
cd /path/to/ore
expand_path ../are
#=> /path/to/are
find_up
find_up [filename]
- ディレクトリを遡って、直近のファイル名が
filename
であるファイルのパスを出力します - ファイル名を省略すると
.envrc
が検索されます
cd /path/to/ore
touch dore
cd are/sore
pwd
#=> /path/to/ore/are/sore
find_up dore
#=> /path/to/ore/dore
PATH_add
PATH_add <path>
- 環境変数
PATH
に指定したパスを追加します - 相対パスを指定した場合でも絶対パスに変換されてから追加されます
echo $PATH
#=> /usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
cd /path/to/ore
PATH_add bin
echo $PATH
#=> /path/to/ore/bin:/usr/local/bin:/bin:/usr/bin:/usr/local/sbin:/usr/sbin
path_add
path_add <varname> <path>
- 環境変数の名前を指定できる意外は
PATH_add
と同じです
export GOPATH=/path/to/golang
echo $GOPATH
#=> /path/to/golang
cd /path/to/ore
path_add GOPATH go
echo $GOPATH
#=> /path/to/ore/go:/path/to/golang
プログラミング言語に特有の設定とかもあったりします。詳細はマニュアルを参照してください。
.direnvrc
~/.direnvrc
が存在する場合、.envrc
のロード前にロードされます。
例えば、独自のユーティリティ関数を作ったりできます。
# ~/.direnvrc
aws_profile(){
export AWS_PROFILE=$1
export AWS_DEFAULT_PROFILE=$AWS_PROFILE
}
この関数は .envrc
で使用することができます。
# .envrc
aws_profile oreore
また、stdlib で use
という関数が定義されており、use foo bar
の形式で呼び出すと use_foo bar
という関数が呼ばれるようになっています。なので、~/.direnvrc
で次のような関数を作成しておくと、
# ~/.direnvrc
use_aws(){
export AWS_PROFILE=$1
export AWS_DEFAULT_PROFILE=$AWS_PROFILE
}
.envrc
で次のように使用することができます。
# .envrc
use aws oreore
Loading layered .envrc
次のように複数の階層に .envrc
が存在していた場合。
/a/.envrc
/a/b/.envrc
/a/b/
に cd
したときは /a/b/.envrc
が有効になります。
/a/b/.envrc
で source_env
を使うと、上の階層の .envrc
もロードすることができます。
# /a/b/.envrc
source_env ..
もしくは source_up
を使えば、階層を遡って直近の .envrc
が自動でロードされます。
# /a/b/.envrc
source_up
dotenv とのコンパチ
次のように書いておくと、dotenv の .env
を direnv の .envrc
からロードすることができます。
# .envrc
dotenv .env
dotenv の .env
は次のような形式です。
# .env
AWS_ACCESS_KEY_ID="ore-no-key"
AWS_SECRET_ACCESS_KEY="ore-no-secret"
これは RHEL の /etc/sysconfig/
とかに置かれるファイルの形式(=systemd の EnvironmentFile
)と同じです。
例えば、次のようなケースで使えます。
- ローカルでなにかデーモンを開発している
- デーモンに必要な環境変数は
.env
に書いて.envrc
からロード - 開発にしか必要ない環境変数は
.envrc
にそのまま書く - systemd の
EnvironmentFile
で.env
を指定する
direnv exec
exec サブコマンドを使えば、指定したディレクトリの .envrc
が反映された状態でコマンドを実行できます。
direnv exec [DIR] COMMAND [...ARGS]
DIR
を省略すると COMMAND
で指定したファイルのあるディレクトリから .envrc
がロードされます。
例えば、インタプリタとスクリプトを指定する場合は次のように呼び出します。
direnv exec /path/to/project php /path/to/project/hoge.php
スクリプトがそのまま実行可能なら次のように呼び出します。
direnv exec /path/to/project/vendor/bin/hoge
(そういう使い方はしたことありませんが)デーモンとかバッチとかで起動するときにはこのサブコマンドを使うと良いと思います。