path_helper
Today I learned about path_helper
, because I wondered why root
's PATH
variable
contained paths from the user executing sudo
:
alice$ sudo -i root# for e in $(echo ${PATH} | sed 's/:/ /g'); do echo "${e}" | sort; done /usr/local/bin /System/Cryptexes/App/usr/bin /usr/bin /bin /usr/sbin /sbin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin /Library/TeX/texbin /opt/homebrew/bin /opt/homebrew/sbin /Users/alice/bin <--- /Users/alice/.local/bin <--- /Users/alice/.local/venv/bin <---
Where are all these PATH
elements coming from? Looking around we find this
in /etc/profile
:
$ cat /etc/profile [...] if [ -x /usr/libexec/path_helper ]; then eval `/usr/libexec/path_helper -s` fi
There's even a fork a new path_helper implementation
that tackles a few of its shortcomings, but let's not give up on it yet. The
manpage to path_helper
states:
The path_helper utility reads the contents of the files in the directories /etc/paths.d and /etc/manpaths.d and appends their contents to the PATH and MANPATH environment variables respectively. [...] Prior to reading these directories, default PATH and MANPATH values are obtained from the files /etc/paths and /etc/manpaths respectively.
OK, that explains where all these (non-existing) cryptexd paths are coming from:
$ grep -hr . /etc/paths* | sort -u /bin /Library/TeX/texbin /sbin /System/Cryptexes/App/usr/bin /usr/bin /usr/local/bin /usr/sbin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin
But there's nothing in there to include the calling user's PATH
elements too.
So maybe path_helper
looks a the wrong user then?
alice$ sudo -i # whoami root # who -m alice ttys006 22 Sep 09:45
A quick workaround would be use sudo
in combination with su
, although
who -m
holds the same information:
alice$ sudo su - root# who -m alice ttys006 22 Sep 09:45 root# eval $(/usr/libexec/path_helper) root# for e in $(echo ${PATH} | sed 's/:/ /g'); do echo "${e}" | sort; done /usr/local/bin /System/Cryptexes/App/usr/bin /usr/bin /bin /usr/sbin /sbin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/local/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/bin /var/run/com.apple.security.cryptexd/codex.system/bootstrap/usr/appleinternal/bin /Library/TeX/texbin
With not much to go by we can still workaround this in our own ~/.profile
:
if [ -n "${SUDO_USER}" ]; then PATH_NEW=$(for e in $(echo ${PATH} | sed 's/:/ /g'); do echo ${e} done | grep -ve /Users/ \ -e /opt/homebrew/ \ -e /var/run/com.apple.security.cryptexd/ \ -e /Library/TeX/texbin \ -e /System/Cryptexes | xargs echo | sed 's/ /:/g') export PATH="/opt/homebrew/bin:/opt/homebrew/sbin:${PATH_NEW}" fi
Yes, it's not pretty, but it does the job. Maybe I should switch to yb66/path_helper after all?