OS: Ubuntu Desktop 22.04
I am initially logged in as user carl. I open a shell and echo $0, I get the confirmation that I am in a non-login shell. ("bash", no dash)
But when I then echo $PATH I see that $HOME/.local/bin and $HOME/bin are both sourced, which is neither declared in ~/.bashrc nor in /etc/environment.
The answer from this thread indicated inheritance from the logged in user.
So I tested a few things:
$ su - root
$ echo $0
> -bash
$ echo $PATH
> /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ su carl
$ echo $0
> bash
$ echo $PATH
> /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ su - carl
$ echo $0
> -bash
$ echo $PATH
> /home/carl/.local/bin:/home/carl/bin:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
$ su carl
$ echo $0
> bash
$ echo $PATH
> /usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:/usr/games:/usr/local/games:/snap/bin
In this example, after logging in as root, then switching to non-login usershell, the PATH variable is as it should be. Then I check if logging in as carl and then switching to non-login shell as carl inherits the logged in shells variable and it doesn't.
Additional considerations:
- "run command as login shell" is unchecked
- No cross reference in .bashrc to source .profile or any other file
- no .bash_login or .bash_profile files exist
- Reboot changes nothing
I am officially out of guesses and would much appreciate a penguin guru to enlighten me so that I can sleep again.
Best Answer
The
.local/bin
is added by default by~/.profile
(copied from/etc/skel/.profile
):.profile
is the correct place to changePATH
, not.bashrc
.No cross reference in .bashrc to source .profile or any other file
No, it's the other way around.
.profile
sources.bashrc
:Let's go over your example:
If I forcibly (not recommended) use
su
to log in without going through the login shell, I don't get my normal$PATH
I want:However, if I log in normally, the
$PATH
is supposed to beexport
ed to child shells. When you log in throughsu - username
or the GUI, it should source.profile
to set$PATH
. Then this variable will be inherited down from your desktop environment's process, then your terminal emulator, then your bash running inside it.So in a GUI login, the following is a simplified view (ignoring
systemd
details and other processes in between):gdm3
as rootgnome-session
or another DE. This sources .profilegnome-terminal
. Does not source anything. Inherits$PATH
bash
. This is your non-login subshell. It sources.bashrc
not.profile
. It inherits$PATH
from gnome-session via gnome-terminalbash
. This is a subshell if you typebash
again. does the same thing as aboveFor an SSH/
su - username
login (also ignoring PAM details):sshd
as root-bash
This is your login shell. This sources .profile. It does not directly source.bashrc
unless.profile
tells it tobash
This a non-login subshell if you typebash
again. It sources.bashrc
not.profile
. It directly inherits$PATH
from-bash
bash
This is another nested non-login subshell if you typebash
another time. It does the same as the other non-login subshell. It inherits$PATH
from-bash
viabash
This is the intended behavior. Trying to change it may lead to a bug where there are duplicate entries in
$PATH
and it becomes too long.If you really want the original shorter
$PATH
in a non-login shell, you could add some code in~/.bashrc
to detect this situation, and parse and remove stuff from$PATH
.