2

I've read a dozen different answers and talked to a bunch of people and am having difficulty understanding how PATH is calculated in different scenarios. Specifically I'm thinking of

  1. How exactly is PATH calculated for bash?
  2. How exactly is it calculated for other shells? (I assume its shell dependent, but what is the commonality between all shells?)
  3. How exactly is it calculated for GUI apps?
  4. Am I missing another way of launching stuff? Do daemons do something different? (I don't think so? But maybe...)

Additionally I'm on High Sierra now but I'm seeing some people mentioned that this changed at some point?

I've seen this answer and this one but both seem to be focused explicitly on what happens inside of bash.

  • What do you mean by the phrase, "how is PATH calculated?. It's an environment variable that is set – Allan Aug 31 '18 at 14:39
  • @Allan yes but how exactly is it set? It's not just .bash_profile for example because by the time that runs, PATH already has things in it (thats why we add to the front or the back). It is calculated by considering some sequence of sources and running some sequence of scripts but what are those? – George Mauer Aug 31 '18 at 14:40
  • 1
    I voting to close this question as too broad. Please edit the question to limit it to a specific problem with enough detail to identify an adequate answer. Avoid asking multiple distinct questions at once. – user3439894 Aug 31 '18 at 14:47
  • @user3439894 Would you recommend asking each of these as a separate question? Because that seems like it would be a massive amount of overlap and some of the answers are likely to be identical. – George Mauer Aug 31 '18 at 14:57
  • It is indeed a very broad question. But here are a few pointers: bash and other bourne-style shells, and also csh and related shells, would use path_helper to help set the PATH variable. Check out its manual page; you will find that they read /etc/paths and /etc/paths.d/* for the contents. Users of other shells are well advised to adapt this method; in that way, all shells get the same PATH. – Harald Hanche-Olsen Aug 31 '18 at 15:02
6

I'm going to lump together 1 & 2 because all shells read files at startup.

PATH is inherited from its parent process. This is a key concept that you need to understand.

The PATH is first hard coded into the kernel:

sysctl user.cs_path
user.cs_path: /usr/bin:/bin:/usr/sbin:/sbin

launchd which acts as init can be configured to change this PATH. Generally it is not changed.

The loginwindow.app will setup an environment when you log into your computer. PATH will be checked that it has been set or it will be set to the hard coded path in the kernel or a modified path set by launchd. It is like the loginwindow.app is calling login -pf <username>.

At this point, a user LaunchAgent or LaunchDaemon may modify the PATH.

This will be the PATH available to GUI applications from the Finder. (Early versions of OS X could use ~/.MacOSX/environment.plist to change the PATH for GUI applications). Now if this seems complicated, it's not and more that likely,like me, the PATH available is /usr/bin:/bin:/usr/sbin:/sbin

When you start the Terminal.app, it first calls login (login -pf ) which triggers your shell to be treated as a login shell. The appropriate files in /etc and your HOME folder are read. Now, PATH should be different than set by the loginwindow.app. Remember we talked about inheritance? If you start a GUI app from within your terminal session then the PATH available to GUI application will be same as set by the shell.

As far as daemons, they are usually started by their absolute path.

  • Thank you for frigign explaining how launchd fits into all this! Nobody else could tell me! – George Mauer Sep 1 '18 at 16:35
  • Launched is just another process and works like all others. It inherits an environment and sets an environment for processes it forks. – Mark Jan 12 at 7:58
4

From the man page for PATH (man path):

The search path for commands. It is a colon-separated list of directories in which the shell looks for commands (see COMMAND EXECUTION below)....The default path is system-dependent, and is set by the administrator who installs bash. A common value is ``/usr/gnu/bin:/usr/local/bin:/usr/ucb:/bin:/usr/bin''.

So, from that except from the bash man page, we see that the bash path is (initially):

  • system dependent and not shell dependent
  • set by the one who installed bash (in this case Apple)
  • has a default value

The path can (obviously) be modified. There are several places where the PATH environment variable can be set:

  • ~/.bashrc
  • ~/.bash_profile

In macOS, the file /etc/paths is used to configure the search paths:

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

Additionally, the path is initially configured by the /usr/libexec/path_helper utility which will create a path based on the contents of /etc/paths.d

It's called from /etc/profile which sets the system wide bash profile (individual ones are set in ~/.profile)

As for GUI apps, the shell path really has no effect. The only time a GUI application (Cocoa, Quartz, Metal) has anything to do with PATH is when it opens a shell (either interactive or non-interactive). At that point it will use the PATH environment as set or make whatever changes it needs at run time.

Different Shells

Each of the shells have a different system wide profile (as does bash) which set's the initial PATH (by calling the path_helper utility)

  • Zsh = /etc/zprilfe
  • Ksh = /etc/profile
  • Csh = /etc/csh.login
  • Yeah, but not everything is launched via bash, right? If I run eshell in emacs or korn shell then its not going to go through the same process. I realize its going to be different per shell, but is it entirely different or does the OS provide a "common base of initialization"? What about apps launched via spotlight? How is the PATH that they see calculated? – George Mauer Aug 31 '18 at 14:59
  • Terminology is important - the path isn't calculated. It's set. You're confusing OS with shell. A shell is nothing more than an environment to execute commands in an OS. – Allan Aug 31 '18 at 15:04
  • Fair enough Allan, I'm not sure what other term to use though. The path is indeed set (from the point of view of the scripts) but from the point of view of an application that might use the PATH, there was a series of steps that were done to produce the current PATH env variable. As for GUI apps, you not using the PATH is different from it not being available. You can do system attribute PATH or something in AppleScript, right? The value that I see there...where does it come from? What series of steps did the OS go through to set it? – George Mauer Aug 31 '18 at 15:12
  • 1
    This is sounding more and more like you have an XY Problem. What's the issue that you're running into because AppleScript doesn't need to have a shell path set. – Allan Aug 31 '18 at 15:25
  • 1
    This is why it's being flagged (I haven't) as too broad. The first thing I would have you look at is the Bash Reference Manual which will give you a good primer on how this stuff works. – Allan Aug 31 '18 at 15:31
0

All: Please understand that Apple has changed the Paths paradigm over time in Sierra (see https://lluad.com/blog/os-x-system-path/) , HighSierra, and Mojave. Path_helper now works somewhat differently it seems because it has locked up terminal windows for me that I can free and have working fine by commenting out

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

in /etc/profile.

I have scripts that fix the path because I have several tools working, (the core of them is installed by Homebrew, but that is only about 15 of the 25 that I use every day) and these have to be set for use in .app applications, in .sh script startups, and for autolaunch in protected boot sequence under Mojave. It is confusing, but for sure Mojave has changed the structure required and I need to step it up myself.

What this means for this particular question is that the question is pertinent in all its breadth and that it needs to be answered by devs who have felt the pain and fixed their systems for Mojave, and also come from the various 'worlds' like normal IDE's, XCode, Eclipse, Bean, Intellij, etc. Also, those who depend upon homebrew stacks, or mamp stacks, etc. And for those who are doing docker, .node, vm, etc. work, and other deeper tools. As Apple implements greater security our stuff is going to break, but I am glad that Apple is doing their job. We need to do ours so we need leading edge folks to pass the new wisdom. Articles that are 6 or more months old are just going to confuse us.

  • Somehow this doesn’t seem to answer the question asked above. If the answer is on the page you linked please summarize it directly in your post (and maybe shorten the later paragraphs). Also, don‘t just mention that you do things differently, but also explain/show show how you do it. – nohillside Jan 12 at 7:27

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .