Mastering the path_helper utility of MacOSX

Aimed to simplify path management, path_helper, the new tool introduced in Leopard that help manage the PATH environment variable, has probably not been as welcome as it should have been, particularly because it is not well documented. We try to shed some light on this obscure tool.

path_helper is located in /usr/libexec. By itself, this tools is armless, since it does not change anything in your environment, it is just a bash or csh commands generator for constructing PATH and MANPATH environment variables based on some text files located in /etc.

So, try it !

More then thousand words, lets run it:

$ /usr/libexec/path_helper
PATH="/usr/local/bin:/usr/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/X11/bin:/usr/local/apache-maven/apache-maven-2.0.9/bin"; export PATH
MANPATH="/usr/share/man:/usr/local/share/man:/usr/X11/man"; export MANPATH

The commands it output are not executed unless you call the same command in an eval like what it is done in the /etc/profile, which is the default startup script for bash shell:

if [ -x /usr/libexec/path_helper ]; then
	eval `/usr/libexec/path_helper -s`
fi

But, how does it construct these paths ?

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.
Files in these directories should contain one path element per line.

This excerpt is so clear that I would not try to say it another way. This is perfectly exact and work pretty well. Moreover, it should have been specified that it reads these file in alphabetical order, so you may use filenames to decide what should come first in your path, since path order is significant. However, this doesn't seem to be really true, it effectively read those files in the order returned by the underlying file system, which for HFS+ happens to be the alphabetical order. Apparently, with this new APFS file system, this isn't true anymore. This is obviously an issue for managing the path properly (Thanks to Dan Kegel for having brought this precision).

However, according to its manpage, before proceeding, path_helper reads its initial values from /etc/paths and /etc/manpaths respectively. 

Since initial values for /etc/paths is

/usr/bin
/bin
/usr/sbin
/sbin
/usr/local/bin

That may seems exact, however this is not fully the truth, at least starting with 10.5.3, because it does not read these files as initial values, but as additional values like in /etc/paths.d. So these files should just be seen as the first file of /etc/paths.d and /etc/manpaths.d respectively, no more.

So well, what are the initial values than. The initial values are the values of the PATH and MANPATH variables when the command gets called ! Since path_helper is a clever tool, it does not duplicate paths, and just append additional unique values to the existing path.

So if the initial PATH variable contains /usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin before calling path_helper, this will remains in front of the path constructed, whatever the /etc/paths ou /etc/paths.d contains.

Pratice

If you want to add additional value to your path, this is very easy, you just have to create a new file in /etc/paths.d and put, on per line, additional paths that are required.

However, if you want to change the order of path lists in /etc/paths, changing the order of lines in this file seems useless ! This because the PATH variable has an initial value of {/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin} before a call to path_helper take place. While the origin of this initial value stay obscure to me, this is a true fact.

Therefore, if you want to place /use/local/bin in front of your path, you have to clean it before calling path_helper. This should be done in 3 files:

  • /etc/csh.login
  • /etc/profile
  • /etc/zprofile or /etc/zshenv depending on your MacOS version

Just add a line PATH="" before the call to path_helper like this in /etc/profile:

if [ -x /usr/libexec/path_helper ]; then
	PATH=""
	eval `/usr/libexec/path_helper -s`
fi

That way, you clean up the path before building it, which is exactly what you had expected from the description of path_helper.

Conclusion

I hope that you have appreciated this information regarding path_helper, and that you now have a better opinion of this tool that is, in fact, initially aimed to simplify application deployments that require PATH changes.