Linux sysadmin question (since it's no longer possible to find actual answers via search on the Internet):

How can I configure the PATH to *always* have a specific directory in it when a shell (Bash) is started, regardless of whether the shell is login/non-login, interactive/non-interactive, etc.?

The normal steps (adding a file in /etc/profile.d which adds to the path) work for login/interactive shells, but not for shells opened by sshd with a command to execute (no pty).

#Linux #SysAdmin #LinuxSysAdmin

I'm going to punt on this, and just symlink the needed binaries/scripts into /usr/local/bin, which is already in the PATH.
@kevin I used to do just that but then I found that ~/.local/bij appears to end up in PATH quite reliably so I am trying that for a bit now
@kevin I think you need to add it to .bashrc
@frank Unfortunately no - adding in /etc/bash.bashrc or in ~/.bashrc does not set PATH when running 'ssh <host> export'.
@frank Adding 'export FOO=bar' in `/.bashrc` does work if it is added at the top - the standard .bashrc on Debian doesn't do anything for non-interactive shells. Grrr.

@kevin In Ubuntu it could be /etc/environment and/or /etc/security/pam_env.conf.

But it is processed by pam, (man pam_env), so you probably have to set UsePAM yes in /etc/ssh/sshd_config.

You can also add Environment option in ssh.service and define PATH for sshd process and it's children.

@kevin Look up .bashrc - or /etc/bashrc
@krahabors I just tried it... cannot make it have any visible effect, in spite of the Bash docs saying it will be executed in a shell started by sshd.

@kevin "man bash" is still ok.

Bash has an option for this, and this option has a default -so it's always active:
--rcfile file

Should point you to /etc/bash.bashrc or something (not on a computer right now)

@kevin This is for Bash specifically. Each shell works a bit differently.

For login shells (interactive or not), it runs `/etc/profile`, then `~/.bash_profile`, `~/.bash_login`, and `~/.profile`.

For interactive non-login shells, it runs `~/.bashrc`.

For non-interactive non-login shells, you have to set `BASH_ENV` to a script to run before you run Bash. You need to give the full path of the script, I think.

If you are running a script or command over sshd (rather than logging in and interacting with commands as usual), it'll run `~/.bashrc`.

Here's the doc page: https://www.gnu.org/software/bash/manual/html_node/Bash-Startup-Files.html

Bash Startup Files (Bash Reference Manual)

Bash Startup Files (Bash Reference Manual)

@bryanredeagle Sadly the default ~/.bashrc (at least on Debian) exits immediately if the shell is non-interactive, so that doesn't help much and of course it isn't global. Thanks though 🙂

@kevin Then Debian is probably doing something before it gets to your `.bashrc`.I think maybe in `/etc/bash.bashrc` (but that might just be Ubuntu...).

If you're willing to switch to Zsh, they have the `.zshenv` file. It is always ran in every shell, and is ran first.

@kevin

Search for the invocation section of man bash.

It lists the order the configuration files are processed in, /etc/profile should be first and for both interactive and non-interactive shells.

Though something else later might override setting the PATH?

Also you might also need to add an export PATH in in whatever script you change the path in.

@kevin This is probably a security measure by sshd. Try looking at its documentation.
@kevin probably something like PermitUserEnvironment yes

@kevin In at least a couple of your replies you've talked about the default Debian .bashrc as though it's an immutable fact of life.

Delete it!

I keep everything in my .shrc and have my .profile source it. I get precisely the same environment everywhere, doing this. I use these same rc files everywhere.

My .shrc sets the right prompt based on whether it's root or non-root. It also uses one pattern for PS1 in bash, since bash is buggy and can't count emitted characters correctly, and another for shells that don't have counting bugs - oksh for instance.

There's no reason to stick with the defaults, and you can even set up custom skeletons so your new users get functional rc scripts from the start.

@kevin This is a complicated question, more so than people think. Among many attempts to explain it that you have no doubt found is this one: https://linuxize.com/post/bashrc-vs-bash-profile/ but the short answer is there is no good way to do this for everything, you need to have your use case(s) in mind and mapped out and provide for each of them. Just when you think you've got it figured out, another comes along, so try, rinse, and repeat if needed.
.bashrc vs .bash_profile: What is the Difference?

Understand the difference between .bashrc and .bash_profile, when each file is loaded, and where to put aliases, PATH changes, and environment variables.

Linuxize

@kevin I've run into same pain. my two shotgun solutions:

1. always cite absolute path to your desired exe. so much BS goes away. DONE

or

2. revise all those scattered env-setting config files so each one imports/sources a single specific common file (like in .sh format), under the hood, that ensures PATH has the path prefix in it, adding it if needed at beginning or end

I don't think I've ever had 1 or 2 not suffice

The problem with relying on PATH is that some code is also sensitive to its CWD/PWD at runtime. To extend the shotgun approach I sometimes force those env values too inside scripts, so they are less fragile

environment.d(5) - Linux manual page

If you allocate a tty (ssh -t command) that should do your bash login and run all your dot files (same as bash -i or sudo -i command)

I usually put things in .bashrc and have to check for a terminal before doing any output as that breaks rsync/scp/sftp if you have any output in there.

@kevin

@kevin I'm late to this party but in cases like this I try to reverse-engineer how it currently works. In this case I'd try finding out where the current path is set and put it in the same place:

grep -r /usr/local/bin /etc