rvm or the Ruby Version Manager, works perfectly fine when there is a single version of Ruby to be run on the system (among multiple versions installed, of course) around the entire system. In a production scenario, updating ruby itself is a task which is not taken lightly!
This worked perfectly until I encountered two quite different situations –
One scenario was where I wanted to execute a command via
ssh into the server. So something like –
ssh user1@server1 'ruby ~/program.rb'
The other being when I wanted to run a ruby program via
In both these cases, I kept getting the error
rvm not found. Initially, I couldn’t understand this at all, because every time I logged in and ran the program or the command it would run prefectly.
And then I learnt about the difference between a login and a non-login shell.
A login shell is created after a successful login of a user or via the switch user
su - user1 command.
This executes the following in order –
/etc/profileexecutes all scripts in
- executes the user’s
~/.bash_profileexecutes the user’s
A non-login shell, on the other hand, executes the following in order –
- executes the user’s
/etc/bashrccalls the scripts in
A key thing to note here is that the user’s
.bashrc gets executed in both the steps.
Now, one of the lines right at the top of the
.bashrc script is this –
# If not running interactively, don't do anything [ -z "$PS1" ] && return
Since a non-login shell is not running interactively, the return gets executed. Anything further down, doesn’t.
rvm, we need to source the following in our
.bashrc file –
[[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm"
If this line is added at the bottom of the
.bashrc, then the non-interactive shell never gets to source
Because of this, it should always be added towards the top of the
.bashrc file before the check for the non-interactive shell.
I added an additional comment to indicate why it is there –
# IMPORTANT - load rvm for non-login shells e.g. Net:SSH [[ -s "$HOME/.rvm/scripts/rvm" ]] && source "$HOME/.rvm/scripts/rvm" # If not running interactively, don't do anything [ -z "$PS1" ] && return