138

I can't seem to set a new $PATH such that it is used when executing commands via ssh user@host command. I have tried adding export PATH=$PATH:$HOME/new_path to ~/.bashrc and ~/.profile on the remote machine, but executing ssh user@host "echo \$PATH" shows that the change has not been picked up (it shows /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games). The remote machine is running Ubuntu 8.04.

I'm sure I could hack it into /etc/profile, but that's not a clean solution and it only works when one has root access.

Denver Gingerich
  • 1,587
  • 2
  • 12
  • 6
  • 1
    I have tried adding `export PATH=$PATH:$HOME/new_path` to both ~/.bash_login and ~/.bash_profile (in addition to the previously-tried ~/.bashrc and ~/.profile). Neither works. In both cases I had to create the file. – Denver Gingerich Jun 02 '09 at 16:49
  • In my particular use case, it is not easy to modify the command sent to ssh. I am using stfufs (http://www.guru-group.fi/too/sw/stfufs/), which constructs the ssh command itself. I realize its method is not a great solution, but it would be nice to fix it without modifying stfufs. – Denver Gingerich Jun 02 '09 at 17:22
  • You could put an ssh wrapper in stfufs' way, call the real ssh with modified args, if that's easier – Hasturkun Jun 02 '09 at 20:25
  • just notifying that in this example there is a chance that you won't get the expected result due the double-quotes. see https://serverfault.com/questions/368327/difference-between-single-quotes-and-double-quotes-when-passing-command-through – HaReL Jun 27 '23 at 12:40

6 Answers6

191

As grawity said, ~/.bashrc is what you want, since it is sourced by non-interactive non-login shells.

I expect the problem you're having has to do with the default Ubuntu ~/.bashrc file. It usually starts with something like this:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

You want to put anything for non-interactive shells before this line.

singpolyma
  • 10,999
  • 5
  • 47
  • 71
  • 3
    Yep, I moved the `export PATH=$PATH:$HOME/new_path` above that line and it worked. Thanks! – Denver Gingerich Jun 02 '09 at 21:38
  • 3
    .bashrc is unreliable. man bash: "Bash attempts to determine when it is being run with its standard input connected to a network connection". This works on RHEL, but not on Archlinux. I had to edit /etc/environment to change the default PATH – basin Apr 24 '13 at 04:22
  • 3
    You should add mention of `.zshenv` for zsh users, it took me quite a while to find it in the comments on other answers – Mike Feb 24 '19 at 12:56
  • on MacOS Catalina, I had to put a "zshenv" file at /etc/zshenv (with my export paths). – Doomd Sep 09 '20 at 23:59
  • @Doomd: did ~/.zshenv not work for you? It worked for me... And yes, this answer would benefit from being edited to include information for various other shells, as well (zsh, fish, ...) – lindes Jan 26 '22 at 02:29
30

Do you have an ~/.bash_login or ~/.bash_profile?

Bash in interactive mode checks for these files, and uses the first existing one, in this order:

  1. ~/.bash_profile
  2. ~/.bash_login
  3. ~/.profile

So if you have an ~/.bash_profile, then whatever changes you do to ~/.profile will be left unseen.

Bash in non-interactive mode sometimes reads the file ~/.bashrc (which is also often source'd from the interactive scripts.) By "sometimes" I mean that it is distribution-dependent: quite oddly, there is a compile-time option for enabling this. Debian enables the ~/.bashrc reading, while e.g. Arch does not.

ssh seems to be using the non-interactive mode, so ~/.bashrc should be enough. When having problems like this, I usually add a few echo's to see what files are being run.

user1686
  • 13,155
  • 2
  • 35
  • 54
  • Adding the echos helped... but I'm still chasing down a way to execute 'ssh -X remotemachine "xterm"' and have the full system / user path from /etc/profile and ~/home/username/.bash_profile. If I source both file in the command, it works.. but its ugly : ). – Jess Apr 03 '13 at 22:18
  • How do you know that "Bash in non-interactive mode reads the file `~/.bashrc`"? I do not see this statement in the manpage. Thanks – nknight May 01 '13 at 22:45
  • 4
    If you want a non-interactive non-login shell to source `~/.bashrc`, it seems that you need to additionally set the environment variable `BASH_ENV`; see http://superuser.com/a/585699/100843 . For non-interactive login shells, you'd probably have to modify one of the three startup scripts you mentioned. – nknight May 01 '13 at 22:52
  • 4
    For ZSH the non-interactive file is: `.zshenv` – math Mar 10 '14 at 15:36
  • 3
    @math `.zshenv` is always sourced; it doesn't matter if it's interactive or not. – JoL Mar 01 '17 at 23:54
20

ssh documentation says:

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

which is why adding to the bashrc files doesn't work. you do however have the following options:

  1. If the PermitUserEnvironment option is set in the sshd config, you can add your PATH setting to ~/.ssh/environment

  2. ssh remotemachine 'bash -l -c "somecommand"'

Hasturkun
  • 35,395
  • 6
  • 71
  • 104
  • 1. It's not set in my sshd config and `man sshd_config` says it's off by default so it's unlikely this solution would work for most people. 2. This would work, but I can't easily modify the command sent to ssh (see the second comment on my question). – Denver Gingerich Jun 02 '09 at 17:24
  • 1
    1. Does not work as expected, because in ~/.ssh/environment, you cannot add pathes to PATH, because $PATH will not be resolved. – not2savvy Mar 10 '17 at 16:42
8

You can always say:

ssh remotemachine 'export PATH=wedontneedastinkingpath; echo $PATH'
Chas. Owens
  • 64,182
  • 22
  • 135
  • 226
3

In addition to @signpolyma answer, you will have to add your export before these lines

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac
  • I actually just commented out these lines altogether - found in ~/.bashrc in Ubuntu 16.04 LTS desktop. No everything works. Also set PermitUserEnvironment to yes. – Ernie S Jan 26 '17 at 00:57
2

Just had the same problem myself, solved it with:

ssh user@remotehost PATH=\$HOME/bin:\$PATH\; remote-command
mkj
  • 2,761
  • 5
  • 24
  • 28
Indie
  • 2,015
  • 1
  • 12
  • 2