yum
upgrades for production use, this is the repository for you.
Active subscription is required.
The PATH
environment variable
For those unfamiliarly with what it is. The PATH
environment variable controls which directories are being checked when you are attempting to run a program.
In other words, it helps construct the complete path to the program while searching for it across the specific directories.
Separated by a semicolon, the directories are listed in this variable’s value in the order of priority, with priority decreasing from left (highest) to the right (lowest) e.g.
PATH=/usr/local/bin:/usr/bin
The PATH
customization per user
A Linux OS user can set up their own, user-specified PATH
. This allows to easily launch user-installed programs. And to give priority between running different versions of the same program.
While doing my writeup on Faster PHP CLI and Cron Jobs, I have found quite a few inconsistencies about where you put the PATH
environment variable customization for a user. Specifically for CentOS/RHEL systems.
Would you customize your PATH
in the ~/.bashrc
or ~/.bash_profile
files?
And what it should be customized to initially?
&tldr; Scroll down to “The solution-workaround” section
The right ways:
- The canonical and recommended approach is having
PATH
and itsexport
in~/.bash_profile
only. - The canonical way of how things work is that
~/.bash_profile
is being used forssh user@example.com command
invocations.
Unfortunately, none of this applies to CentOS/RHEL 7 and 8. Here’s why and what to do about it.
The defaults are quite different between CentOS/RHEL 7 and 8.
How CentOS 7 does it (wrong)
A new user gets PATH
added to ~/.bash_profile
and it’s set to
PATH=$PATH:$HOME/.local/bin:$HOME/bin
So initially it is /sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/home/foo/.local/bin:/home/foo/bin
Setting PATH
in ~/.bash_profile
is correct because it prevents “double-sourcing” PATH
. If it was put to ~/.bashrc
, running subshell, e.g. echo $(command)
, would source the file many times, and this would result in a lengthy PATH
with duplicate directories for the subshells.
However, $PATH:$HOME/.local/bin:$HOME/bin
is not good in case we want to override system programs with user’s installed programs or custom wrappers, like in the Faster PHP CLI and Cron Jobs.
But the other “bad” thing, if you will, is that running non-interactive commands over SSH, will not include our user-specific PATH
, e.g.
ssh user@example.com command
will not have ~/.local/bin
included, because only ~/.bashrc
is used for such a case!
How CentOS 8 does it (“work in progress”)
CentOS/RHEL 8 had a history of changes in the way custom user PATH
was included to either ~/.bashrc
or ~/.bash_profile
.
It was present in 8.0 in ~/.bash_profile, then in ~/.bashrc
in subsequent versions. Seems that this is the very part where developers didn’t make up their mind.
At one point between those changes, double-sourcing PATH
s was possible, which means that subshells would see this PATH
:
/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/home/foo/.local/bin:/home/foo/bin/sbin:/bin:/usr/sbin:/usr/bin:/usr/local/sbin:/home/foo/.local/bin:/home/foo/bin
Or even lengthier, depending on the nesting.
The latest versions of CentOS/RHEL 8 almost got it right, except that command over ssh
still do not source ~/.bash_profile
, and source ~/.bashrc
instead, for whatever reason.
So it gets “work in progress” label from me.
What you see is what you got
Worth noting that how your specific ~/.bashrc
or ~/.bash_profile
looks now depends on the way skeleton files were at the time your user was created.
You can find the skeleton files, in e.g. /etc/skel/.bash_profile
.
The solution-workaround
In most situations, we:
- want commands run via
ssh user@example.com command
to use our custom `PATH. - don’t want to double-source our
PATH
statement causing duplication - want our
PATH
to use the customization for interactive SSH sessions
So the solution is non-intuitive and non-standard and follows up pretty much with the latest RHEL 8 thinking. Set your custom path in ~/.bashrc
only
# User specific environment
if ! [[ "$PATH" =~ "$HOME/.local/bin:$HOME/bin:" ]]; then
PATH="$HOME/.local/bin:$HOME/bin:$PATH"
fi
export PATH
The condition prevents double-sourcing, even though we use the non-canonical ~/.bashrc
location for our PATH
customization.
In this way, finally, things at least will work the right way and as expected.