Amazon LinuxだとCapistranoでrailsアプリをデプロイする時、特に設定しなくてもデプロイユーザーの環境変数がそのまま設定されていたのに、Ubuntuでは設定されていなかった。non interactive、non loginセッションで実行される場合、Ubuntuでは読み込むファイルが違うようだった。

結論を先に書くと、Ubuntu 16.04では~/.bashrcはnon interactive、non loginセッションでも読み込まれるので、ここに書いておけば良い。

各種スクリプトの読み込み順

sshでログインした場合

  1. /etc/profile
  2. /etc/bash.bashrc
  3. ~/.profile
  4. ~/.bashrc

non interactiveセッションの場合

  1. /etc/bash.bashrc
  2. ~/.bashrc

この場合、/etc/profile~/.profileも読み込まれない。/etc/profileでは

  1. /etc/bash.bashrcの読み込み
  2. /etc/profile.d/*.shの読み込み

が実行されている。

/etc/profile
# /etc/profile: system-wide .profile file for the Bourne shell (sh(1))
# and Bourne compatible shells (bash(1), ksh(1), ash(1), ...).
if [ "$PS1" ]; then
if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "`id -u`" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
if [ -d /etc/profile.d ]; then
for i in /etc/profile.d/*.sh; do
if [ -r $i ]; then
. $i
fi
done
unset i
fi

つまり、/etc/profile.dの配下にrbenvやnodebrewといったツールの環境変数設定用スクリプトを置いても、non interactiveセッションでは適用されない。Capistranoでデプロイする時の落とし穴であった。

さらに、non interactiveセッションの場合([ -z "$PS1" ])、/etc/bash.bashrcではすぐにreturnされているので、このスクリプトも実質的に何も実行されないのと変わらない。

/etc/bash.bashrc
# System-wide .bashrc file for interactive bash(1) shells.
# To enable the settings / commands in this file for login shells as well,
# this file has to be sourced in /etc/profile.
# If not running interactively, don't do anything
[ -z "$PS1" ] && return

というわけで、Ubuntu 16.04でnon interactiveセッションでも環境変数などの設定ができる唯一の場所は~/.bashrcとなる。