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 be 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 command 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 comes first in your path, since path order is significant.

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 value are the value of the PATH and MANPATH variables when the command get called ! Since path_helper is a clever tools, 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, what ever 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 cleanup the path before building it, which is exactly what you had expect from the description of path_helper.

Conclusion

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