[Exherbo-dev] Preserving PATH during shell startup

Bernd Steinhauser exherbo at bernd-steinhauser.de
Sun Oct 28 13:18:21 UTC 2012


Currently, the way we handle the system environment variables is the use of 
/etc/env.d, which gets merged by `eclectic env update` to /etc/profile.env.
In both /etc/profile (used by bash) and /etc/zsh/zprofile (used by zsh), 
/etc/profile.env is sourced unconditionally, which contains `export 
PATH='some:paths:'.
This means that once /etc/profile.env has been sourced, PATH has been reset to 
whatever is in profile.env + whatever bash or zsh add to it in their startup files.
This has two consequences:
1. You can not pass a custom PATH to a subshell, if the subshell runs one of the 
startup files that is sourcing /etc/profile.env (I'm 100% sure about the 
situation for bash, I think it only does so if run as a login or interactive shell)
2. Only the case for zsh: A user-customized PATH (in ~/.zshenv) might get 
overridden if run as an interactive or a login shell (because we set PATH in 
/etc/zsh/{zprofile,zshrc}. See the ordering of the startup files in [1]. 
Currently, we tell users to use .zshrc for that instead.

For zsh, we tried to ship around 1. by setting PATH in zprofile and zshrc, which 
are almost identical, introducing 2.
Since I'm not really happy about this situation, and since it should be ok to 
allow setting or modifying PATH in /etc/zsh/zshenv and ~/.zshenv, I wan't to 
discuss this topic, finding the best solution for exherbo.

One of the solutions (at least for zsh) might be to preserve the current PATH, 
then source /etc/profile.env, and after that restoring or adding the previously 
set PATH. We could also make a change that profile.env is only sourced if a 
condition is met, i.e. [[ -o norcs ]] for zsh. (Actually, it might be desirable 
to do that even if we tend to use a different solution.)

The other solution might be to stop exporting PATH as is in /etc/profile.env. 
This could be for example be done by either renaming the var eclectic merges to 
or renaming the vars in the files in /etc/env.d, i.e. to USERPATH (similar to 
ROOTPATH). The startup scripts could then use USERPATH (and probably ROOTPATH) 
to compose PATH.

For zsh I would therefore propose to use something like this for zshenv:

if [[ ! -o norcs ]]; then
     if [[ -e /etc/profile.env ]]; then
         . /etc/profile.env
     fi
     
PATH="${PATH}:/usr/local/sbin:/usr/local/bin:/usr/sbin:/usr/bin:/sbin:/bin:${USERPATH}:${ROOTPATH}"
     export PATH
     unset USERPATH ROOTPATH
fi

That would mean that a modified PATH is preserved, that . /etc/profile.env is 
only sourced when not running as zsh -f and it will be updated upon every shell 
startup, for both interactive and non-interactive shells, unless explicitly 
specified (-f).

I mainly talked about zsh here, because that's where we actually see the 
problem. I'm not sure about the situation with bash, so I would other people to 
speak up. Maybe bash shows a different behavior, where no problems occur?
Since at least the second solution affects all shells, it might be a good idea 
to discuss it first. Of course, we can just implement the other solution, but 
before we do so for all shells...



More information about the Exherbo-dev mailing list