I've noticed that when I run a command directly on an SSH host using the ssh <host> <command>
syntax, I see the output of .bashrc
but not the output of .bash_profile
(or .profile
).
For instance, if I place the following command at the top of both files,
echo ${BASH_SOURCE[0]}
and manually source .bash_profile
(which sources .bashrc
in turn), I'll see
$ . .bash_profile
.bash_profile
.bashrc
This is the same output I see if I log into this computer remotely via SSH, using the ssh <host>
form of the command. (And if I stow .bash_profile
somewhere else temporarily, neither of these lines gets echoed.)
However, if I execute a command directly on the remote machine with the ssh <host> <command>
form of ssh
, then the output looks like this:
$ ssh <host> echo foo
/home/rlue/.bashrc
foo
My understanding is that the difference between .bash_profile
and .bashrc
is that the former is for login shells while the latter is for interactive, non-login shells.
I've concluded the following:
ssh <host>
sources only.bash_profile
, whilessh <host> <command>
sources only.bashrc
, which means- the former is a login shell and the latter is not.
Are these conclusions correct? Why is ssh <host> <command>
treated as an interactive, non-login shell? Isn't SSH still logging into the remote machine to execute the command?
Best Answer
OpenSSH (most likely what you're running) decides whether or not to create a login shell, and it only does so if you are not running a specific command. From
man ssh
:So it's an implementation choice for the ssh server whether it wants to create a login shell or not, and if you give a command to run, it does not.
While
ssh
does perform a login, if you're having it execute a command and exit, it's really much more similar to creating a shell just to run that command than it is to getting a login environment. It seems, given that, that the people writing OpenSSH decided to treat it like that sort of task.They create a non-interactive, non-login shell to execute the command, because that's the spirit of running a command in another context/shell. Normally, though, non-interactive shells would not automatically source
~/.bashrc
which is clearly happening here.bash
is actually trying to help us out here. From the docs