~/.bash_profile
や~/.bashrc
にPATHの追加設定を書いて、bashの起動時にPATHを自動設定するということを良くやりますが、ATOMのターミナルプラグインであるPlatformIO IDE Terminalを使ってATOM内に起動したシェルのPATHが、iTERM2上のシェルでのPATHと異なってしまい、しばらく苦労してました。
困っていたこと
私は普段~/.bash_profile
で、追加したいパスがPATHになかった場合のみ追加するという処理を書いています。
gnubin_path=/usr/local/opt/coreutils/libexec/gnubin
echo $PATH | grep -q $gnubin_path > /dev/null 2>&1
if [ $? -ne 0 ]; then
export PATH=$gnubin_path:$PATH
fi
iTERM2でシェルを起動したとき、PATHは以下のようになっていました。
$ echo $PATH
/usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
この状態だと、例えばls
コマンドは/usr/local/opt/coreutils/libexec/gnubin/ls
のバイナリを使用します。
$ which ls
/usr/local/opt/coreutils/libexec/gnubin/ls
しかし、ATOM内のシェルでは以下のように/usr/local/opt/coreutils/libexec/gnubin
が後ろに来てしまっています。
$ echo $PATH
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/opt/coreutils/libexec/gnubin
この状態だと、ls
コマンドは/bin/ls
のバイナリを使用してしまいます。
$ which ls
/bin/ls
原因
bashは親プロセスの環境変数を子プロセスに引き継ぎます。
ATOMプロセスのPATHが/usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
になっていると、その子プロセスとなるATOM内シェルのPATHには/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/opt/coreutils/libexec/gnubin
が引き継がれます。
/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
はbashの終了時にPATHから削除され、bashの起動時に自動的にPATHの先頭に追加されるようです。
この状態で.bash_profile
が実行されるので、すでに該当のパスが存在していると判断されて、export PATH=$gnubin_path:$PATH
が実行されません。
解決方法
ATOM内シェルの時のみ、PATHを初期化するという処理を.bash_profile
に加えてあげれば良いです。
現在のシェルがATOM内シェルかどうかは、親プロセスのコマンドにplatformio-ide-terminal/lib/process.coffee
が含まれているかどうかで判断しています。
ps u -p $PPID | grep 'platformio-ide-terminal/lib/process.coffee' > /dev/null 2>&1
if [ $? -eq 0 ]; then
export PATH=/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin
fi
gnubin_path=/usr/local/opt/coreutils/libexec/gnubin
echo $PATH | grep -q $gnubin_path > /dev/null 2>&1
if [ $? -ne 0 ]; then
export PATH=$gnubin_path:$PATH
fi
これでATOM内シェルでも以下のPATHが設定されます。
/usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin