Setting environment variables on OS X

后端 未结 30 3153
你的背包
你的背包 2020-11-21 05:15

What is the proper way to modify environment variables like PATH in OS X?

I\'ve looked on Google a little bit and found three different files to edit:

相关标签:
30条回答
  • 2020-11-21 05:46

    Much like the answer Matt Curtis gave, I set environment variables via launchctl, but I wrap it in a function called export, so that whenever I export a variable like normal in my .bash_profile, it is also set by launchctl. Here is what I do:

    1. My .bash_profile consists solely of one line, (This is just personal preference.)

      source .bashrc
      
    2. My .bashrc has this:

      function export()
      {
          builtin export "$@"
          if [[ ${#@} -eq 1 && "${@//[^=]/}" ]]
          then
              launchctl setenv "${@%%=*}" "${@#*=}"
          elif [[ ! "${@//[^ ]/}" ]]
          then
              launchctl setenv "${@}" "${!@}"
          fi
      }
      
      export -f export
      
    3. The above will overload the Bash builtin "export" and will export everything normally (you'll notice I export "export" with it!), then properly set them for OS X app environments via launchctl, whether you use any of the following:

      export LC_CTYPE=en_US.UTF-8
      # ~$ launchctl getenv LC_CTYPE
      # en_US.UTF-8
      PATH="/usr/local/bin:${PATH}"
      PATH="/usr/local/opt/coreutils/libexec/gnubin:${PATH}"
      export PATH
      # ~$ launchctl getenv PATH
      # /usr/local/opt/coreutils/libexec/gnubin:/usr/local/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin
      export CXX_FLAGS="-mmacosx-version-min=10.9"
      # ~$ launchctl getenv CXX_FLAGS
      # -mmacosx-version-min=10.9
      
    4. This way I don't have to send every variable to launchctl every time, and I can just have my .bash_profile / .bashrc set up the way I want. Open a terminal window, check out your environment variables you're interested in with launchctl getenv myVar, change something in your .bash_profile/.bashrc, close the terminal window and re-open it, check the variable again with launchctl, and voilá, it's changed.

    5. Again, like the other solutions for the post-Mountain Lion world, for any new environment variables to be available for apps, you need to launch or re-launch them after the change.

    0 讨论(0)
  • 2020-11-21 05:46

    The $PATH variable is also subject to path_helper, which in turn makes use of the /etc/paths file and files in /etc/paths.d.

    A more thorough description can be found in PATH and other environment issues in Leopard (2008-11)

    0 讨论(0)
  • 2020-11-21 05:48

    Solution for both command line and GUI applications from a single source (works with Mac OS X v10.10 (Yosemite) and Mac OS X v10.11 (El Capitan))

    Let's assume you have environment variable definitions in your ~/.bash_profile like in the following snippet:

    export JAVA_HOME="$(/usr/libexec/java_home -v 1.8)"
    export GOPATH="$HOME/go"
    export PATH="$PATH:/usr/local/opt/go/libexec/bin:$GOPATH/bin"
    export PATH="/usr/local/opt/coreutils/libexec/gnubin:$PATH"
    export MANPATH="/usr/local/opt/coreutils/libexec/gnuman:$MANPATH"
    

    We need a Launch Agent which will run on each login and anytime on demand which is going to load these variables to the user session. We'll also need a shell script to parse these definitions and build necessary commands to be executed by the agent.

    Create a file with plist suffix (e.g. named osx-env-sync.plist) in ~/Library/LaunchAgents/ directory with the following contents:

    <?xml version="1.0" encoding="UTF-8"?>
    <!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
    <plist version="1.0">
    <dict>
      <key>Label</key>
      <string>osx-env-sync</string>
      <key>ProgramArguments</key>
      <array>
        <string>bash</string>
        <string>-l</string>
        <string>-c</string>
        <string>
          $HOME/.osx-env-sync.sh
        </string>
      </array>
      <key>RunAtLoad</key>
      <true/>
    </dict>
    </plist>
    

    -l parameter is critical here; it's necessary for executing the shell script with a login shell so that ~/.bash_profile is sourced in the first place before this script is executed.

    Now, the shell script. Create it at ~/.osx-env-sync.sh with the following contents:

    grep export $HOME/.bash_profile | while IFS=' =' read ignoreexport envvar ignorevalue; do
      launchctl setenv "${envvar}" "${!envvar}"
    done
    

    Make sure the shell script is executable:

    chmod +x ~/.osx-env-sync.sh
    

    Now, load the launch agent for current session:

    launchctl load ~/Library/LaunchAgents/osx-env-sync.plist
    

    (Re)Launch a GUI application and verify that it can read the environment variables.

    The setup is persistent. It will survive restarts and relogins.

    After the initial setup (that you just did), if you want to reflect any changes in your ~/.bash_profile to your whole environment again, rerunning the launchctl load ... command won't perform what you want; instead you'll get a warning like the following:

    <$HOME>/Library/LaunchAgents/osx-env-sync.plist: Operation already in progress

    In order to reload your environment variables without going through the logout/login process do the following:

    launchctl unload ~/Library/LaunchAgents/osx-env-sync.plist
    launchctl load ~/Library/LaunchAgents/osx-env-sync.plist
    

    Finally make sure that you relaunch your already running applications (including Terminal.app) to make them aware of the changes.

    I've also pushed the code and explanations here to a GitHub project: osx-env-sync.

    I hope this is going to be the ultimate solution, at least for the latest versions of OS X (Yosemite & El Capitan).

    0 讨论(0)
  • 2020-11-21 05:48

    Set up your PATH environment variable on Mac OS

    Open the Terminal program (this is in your Applications/Utilities folder by default). Run the following command

    touch ~/.bash_profile; open ~/.bash_profile
    

    This will open the file in the your default text editor.

    For Android SDK as example:

    You need to add the path to your Android SDK platform-tools and tools directory. In my example I will use "/Development/android-sdk-macosx" as the directory the SDK is installed in. Add the following line:

    export PATH=${PATH}:/Development/android-sdk-macosx/platform-tools:/Development/android-sdk-macosx/tools
    

    Save the file and quit the text editor. Execute your .bash_profile to update your PATH:

    source ~/.bash_profile
    

    Now every time you open the Terminal program your PATH will include the Android SDK.

    0 讨论(0)
  • 2020-11-21 05:49

    While the answers here aren't "wrong", I'll add another: never make environment variable changes in OS X that affect "all processes", or even, outside the shell, for all processes run interactively by a given user.

    In my experience, global changes to environment variables like PATH for all processes are even more likely to break things on OS X than on Windows. Reason being, lots of OS X applications and other software (including, perhaps especially, components of the OS itself) rely on UNIX command-line tools under the hood, and assume the behavior of the versions of these tools provided with the system, and don't necessarily use absolute paths when doing so (similar comments apply to dynamically-loaded libraries and DYLD_* environment variables). Consider, for instance, that the highest-rated answers to various Stack Overflow questions about replacing OS X-supplied versions of interpreters like Python and Ruby generally say "don't do this."

    OS X is really no different than other UNIX-like operating systems (e.g., Linux, FreeBSD, and Solaris) in this respect; the most likely reason Apple doesn't provide an easy way to do this is because it breaks things. To the extent Windows isn't as prone to these problems, it's due to two things: (1) Windows software doesn't tend to rely on command-line tools to the extent that UNIX software does, and (2) Microsoft has had such an extensive history of both "DLL hell" and security problems caused by changes that affect all processes that they've changed the behavior of dynamic loading in newer Windows versions to limit the impact of "global" configuration options like PATH.

    "Lame" or not, you'll have a far more stable system if you restrict such changes to smaller scopes.

    0 讨论(0)
  • 2020-11-21 05:50

    To be concise and clear about what each file is intended for

    • ~/.profile is sourced every time Terminal.app is launched
    • ~/.bashrc is where "traditionally" all the export statements for Bash environment are set
    • /etc/paths is the main file in Mac OS that contains the list of default paths for building the PATH environment variable for all users
    • /etc/paths.d/ contains files that hold additional search paths

    Non-terminal programs don't inherit the system wide PATH and MANPATH variables that your terminal does! To set environment for all processes launched by a specific user, thus making environment variables available to Mac OS X GUI applications, those variables must be defined in your ~/.MacOSX/environment.plist (Apple Technical Q&A QA1067)

    Use the following command line to synchronize your environment.plist with /etc/paths:

    defaults write $HOME/.MacOSX/environment PATH "$(tr '\n' ':' </etc/paths)"
    
    0 讨论(0)
提交回复
热议问题