139

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.

4
  • 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. Commented Jun 2, 2009 at 16:49
  • In my particular use case, it is not easy to modify the command sent to ssh. I am using stfufs (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. Commented Jun 2, 2009 at 17:22
  • You could put an ssh wrapper in stfufs' way, call the real ssh with modified args, if that's easier Commented Jun 2, 2009 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 serverfault.com/questions/368327/… Commented Jun 27, 2023 at 12:40

6 Answers 6

194

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.

Sign up to request clarification or add additional context in comments.

5 Comments

Yep, I moved the export PATH=$PATH:$HOME/new_path above that line and it worked. Thanks!
.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
You should add mention of .zshenv for zsh users, it took me quite a while to find it in the comments on other answers
on MacOS Catalina, I had to put a "zshenv" file at /etc/zshenv (with my export paths).
@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, ...)
31

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.

5 Comments

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 : ).
How do you know that "Bash in non-interactive mode reads the file ~/.bashrc"? I do not see this statement in the manpage. Thanks
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 superuser.com/a/585699/100843 . For non-interactive login shells, you'd probably have to modify one of the three startup scripts you mentioned.
For ZSH the non-interactive file is: .zshenv
@math .zshenv is always sourced; it doesn't matter if it's interactive or not.
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"'

2 Comments

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).
1. Does not work as expected, because in ~/.ssh/environment, you cannot add pathes to PATH, because $PATH will not be resolved.
8

You can always say:

ssh remotemachine 'export PATH=wedontneedastinkingpath; echo $PATH' 

1 Comment

This solution does not need any change on the remote machine, which is a good thing.
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 

4 Comments

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.
@ErnieS That's a bad idea; they are there for a reason.
@tripleee Ok, why? What do they do? Do you have a better solution? I understand you may not like the comment (from 7 years ago which I have no recollection of what I was trying to solve) but only giving a negative comment in response with no alternate suggestions does not help anyone.
The purpose of this logic is to optimize the start of new shells by skipping logic which does not need to be repeated in interactive invocations. It also allows you to conditionally run code only when the shell is interactive.
2

Just had the same problem myself, solved it with:

ssh user@remotehost PATH=\$HOME/bin:\$PATH\; remote-command 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.