shellだけでdirenv的な事をする
direnv、便利ですが人によっては入れたくないという思いもありますし、職場でのアンケートを行うとそもそも知らない、という人もいるようです
今回のそのそもの目的は.ruby-version、.node-version等から値を環境変数にセットし、それを更にRails、Docker、Docker Compose等に渡したいという要望です
これを行うと、.ruby-version、.node-versionだけの変更で一括でバージョン変更が可能となりアップデートが簡単に行えます
Zsh
個人的には未だにBash愛用者ですが、仕事用環境はmacOSですが現在はデフォルトshellがZshとなっていますので対応が必要です
zshではコマンドにHookを行うことが可能です この機能を使って対応します
.zsh_config
を対象ディレクトリに置きます
中身はこの様にします
function setter() { export HOGE=1 } function unsetter() { unset HOGE } case $1 in set) setter ;; unset) unsetter ;; esac
~/.zshrc
側でコマンドをHookします
# cdで移動前に現在のディレクトリの設定を削除 function unset_dir_config() { if [ `echo $1|awk '{print $1}'` = 'cd' ]; then if [ -r $PWD/.zsh_config ]; then source $PWD/.zsh_config unset fi fi } # cdで移動跡に現在のディレクトリの設定を行う function set_dir_config() { if [ -r $PWD/.zsh_config ]; then source $PWD/.zsh_config set fi } add-zsh-hook chpwd set_dir_config add-zsh-hook preexec unset_dir_config
非常に簡単に設定が行えます
Bash
私は普段 はBashを使用しています。そろそろZshにしても良いかもとは思ってますが、あまり慣れるとBash環境を触る時に辛そうだなぁと思いまだ躊躇していますね
さて、Bashではデフォルトの機能ではコマンドをHookする機能が無い?ようでbash-preexecを利用します github.com
.bash_config
は .zsh_config
とファイル名が違うだけで同じで内容は同じなので省略します
~/.bashrc
もほぼ同じです
source ~/bash-preexec.sh preexec_functions+=(unset_dir_config) precmd_functions+=(set_dir_config) unset_dir_config() { PRECMD=`echo $1|awk '{print $1}'` if [ "$PRECMD" == 'cd' ]; then if [ -f $PWD/.bash_config ]; then source $PWD/.bash_config unset fi fi } set_dir_config() { if [ "$PRECMD" == 'cd' ]; then if [ -f $PWD/.bash_config ]; then source $PWD/.bash_config set fi fi unset PRECMD }
応用
特定のコマンドをHook出来るのでそのコマンド専用の環境変数を設定する、何か専用の処理を行う事ができます。 例えば、弊社はCircleCIを利用していますのでCircleCI CLIも利用しています。ローカルでcircleciコマンドを実行する場合にだけ設定を行うという事が可能です
以前から環境変数について悩みどころだったのですが今回必要に迫られたとは言え調べて対応できたので良かったですね 今後色々な場面で利用できそうです