Bash – Can ‘ssh ‘ be configured to always load server-side startup files

bashbashrcssh

I would like run remote ssh commands and have them always load server-side startup files by default. I am looking for a solution that does not require:

  • configuration by root
  • adding extra boiler plate to the command each time
  • duplicating environment variables across multiple files

I am not looking to transport local environment variables to the remote shell. I want to run a remote command using the vanilla ssh <host> <command> syntax and have it run using the same environment a remote login session would get.

Background

The below assumes bash is being used for simplicity

By default, remote ssh commands start a non-interactive, non-login shell. Quoting the man page:

If command is specified, it is executed on the remote host instead of
a login shell.

You can see this more explicitly on the shell by running:

# the lack of 'i' indicates non-interactive
$ ssh localhost 'echo $-'
hBc 

$ ssh localhost 'shopt login_shell'
login_shell     off

But what if your remote command needs certain environment variables set? Being a non-interactive, non-login shell means neither .bash_profile nor .bashrc will be sourced.

This is problematic, for example, if you're using tools like perlbrew or virtualenv and want to use your custom interpreter in the remote command:

$ which perl
/home/calid/perl5/perlbrew/perls/perl-5.20.1/bin/perl

$ ssh localhost 'which perl'
/usr/bin/perl

Solutions that do not satisfy the requirements above

Explicitly invoke a login shell in the remote command

$ ssh localhost 'bash --login -c "which perl"'

Requires extra boiler plate each time

Explicitly source your profile before the command

$ ssh localhost 'source ~/.bash_profile && which perl'

Requires extra boiler plate each time

Set environment variables in ~/.ssh/environment

Requires root to enable this functionality on the server

Duplicates environment variables already set in server startup files

Set ENV and BASH_ENV

Does not work: .bash_profile and .bashrc aren't sourced

Setting in ~/.ssh/environment works, but requires root access to enable

Preface the command with the environment variables you need

Requires extra boiler plate each time (potentially a lot)

Duplicates environment variables already set in server startup files

Related posts

https://stackoverflow.com/questions/415403/whats-the-difference-between-bashrc-bash-profile-and-environment

https://stackoverflow.com/questions/216202/why-does-an-ssh-remote-command-get-fewer-environment-variables-then-when-run-man#216204

dot file not sourced when running a command via ssh

Best Answer

Create a wrapper shell function sshc which prefixes the source ~/.bash_profile boiler plate for you:

function sshc {
    local host=$1
    local cmd=$2

    ssh $host "source ~/.bash_profile && $cmd"
}

You can then use this as:

$ sshc localhost 'which perl'
/home/calid/perl5/perlbrew/perls/perl-5.20.1/bin/perl
Related Question