在 OS X 上设置环境变量

在 OS X 中修改环境变量(如 PATH)的正确方法是什么?

我稍微看了一下 Google,发现需要编辑三个不同的文件:

  • / etc / 路径
  • 〜/ .profile
  • 〜/ .tcshrc

我什至没有这些文件,而且我很确定.tcshrc是错误的,因为 OS X 现在使用 bash。这些变量(尤其是 PATH)在哪里定义?

我正在运行OS X v10.5 (Leopard)。

答案

布鲁诺是正确的。我已经进行了广泛的研究,如果您想设置所有 GUI 应用程序中都可用的变量,则唯一的选择是/etc/launchd.conf

请注意, environment.plist 不适用于通过 Spotlight 启动的应用程序。这是史蒂夫 · 塞克斯顿(Steve Sexton)在此处记录的

  1. 打开终端提示

  2. 键入sudo vi /etc/launchd.conf (注意:此文件可能尚不存在)

  3. 将如下内容放入文件中

    # Set environment variables here so they are available globally to all apps
    # (and Terminal), including those launched via Spotlight.
    #
    # After editing this file run the following command from the terminal to update
    # environment variables globally without needing to reboot.
    # NOTE: You will still need to restart the relevant application (including
    # Terminal) to pick up the changes!
    # grep -E "^setenv" /etc/launchd.conf | xargs -t -L 1 launchctl
    #
    # See http://www.digitaledgesw.com/node/31
    # and http://stackoverflow.com/questions/135688/setting-environment-variables-in-os-x/
    #
    # Note that you must hardcode the paths below, don't use environment variables.
    # You also need to surround multiple values in quotes, see MAVEN_OPTS example below.
    #
    setenv JAVA_VERSION 1.6
    setenv JAVA_HOME /System/Library/Frameworks/JavaVM.framework/Versions/1.6/Home
    setenv GROOVY_HOME /Applications/Dev/groovy
    setenv GRAILS_HOME /Applications/Dev/grails
    setenv NEXUS_HOME /Applications/Dev/nexus/nexus-webapp
    setenv JRUBY_HOME /Applications/Dev/jruby
    
    setenv ANT_HOME /Applications/Dev/apache-ant
    setenv ANT_OPTS -Xmx512M
    
    setenv MAVEN_OPTS "-Xmx1024M -XX:MaxPermSize=512m"
    setenv M2_HOME /Applications/Dev/apache-maven
    
    setenv JMETER_HOME /Applications/Dev/jakarta-jmeter
  4. 在 vi 中保存所做的更改,然后重新启动 Mac。或使用上面的代码注释中显示的grep / xargs命令。

  5. 通过打开 “终端” 窗口并键入export证明您的变量正在工作,您应该会看到新的变量。这些也将在 IntelliJ IDEA 和您通过 Spotlight 启动的其他 GUI 应用程序中提供。

如何为 Spotlight 启动的新进程设置环境(无需重新启动)

您可以使用launchctl setenv设置 launchd(以及扩展名,从 Spotlight 开始的任何东西)使用的launchctl setenv 。例如设置路径:

launchctl setenv PATH /opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

或者,如果要在.bashrc或类似文件中设置路径,则将其镜像到启动状态:

PATH=/opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin
launchctl setenv PATH $PATH

无需重新启动,尽管如果您希望应用程序选择更改后的环境,则需要重新启动它。

这包括已经在 Terminal.app 下运行的所有 shell,尽管如果在那里,您可以直接设置环境,例如,对于 bash 或 zsh,使用export PATH=/opt/local/bin:/opt/local/sbin:$PATH

重新启动后如何保留更改

在重新引导后保留更改,可以从/etc/launchd.conf设置环境变量,如下所示:

setenv PATH /opt/local/bin:/opt/local/sbin:/usr/bin:/bin:/usr/sbin:/sbin

重新启动时会自动执行launchd.conf

如果您希望这些更改现在生效,则应使用此命令重新处理launchctl.conf (感谢 @mklement 提示!)

egrep -v '^\s*#' /etc/launchd.conf | launchctl

您可以使用命令man launchctl了解有关launchctl以及如何加载launchd.conf更多信息。

最高包括OS X v10.7 (Lion),您可以在以下位置进行设置:

~/.MacOSX/environment.plist

看到:

对于终端中的 PATH,您应该可以在.bash_profile.profile进行设置(尽管您可能必须创建它)

对于OS X v10.8 (Mountain Lion)及更高版本, 您需要使用launchdlaunchctl

单一来源的命令行和 GUI 应用程序的解决方案(与Mac OS X v10.10 (Yosemite)和Mac OS X v10.11 (El Capitan)一起使用)

假设您在~/.bash_profile具有环境变量定义,如以下代码片段所示:

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"

我们需要一个启动代理 ,它将在每次登录时按需运行,并随时随地将这些变量加载到用户会话中。我们还需要一个 shell 脚本来解析这些定义并构建必要的命令以由代理执行。

~/Library/LaunchAgents/目录中创建带有plist后缀的文件(例如,名为osx-env-sync.plist ),其内容如下:

<?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参数在这里很关键;必须使用登录 shell执行 shell 脚本,以便在执行此脚本之前首先~/.bash_profile

现在,shell 脚本。使用以下内容在~/.osx-env-sync.sh创建它:

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

确保 shell 脚本是可执行的:

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

现在,为当前会话加载启动代理:

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

(重新)启动 GUI 应用程序,并验证其可以读取环境变量。

设置是持久的。它将在重新启动和重新登录后继续存在。

初始设置(刚刚完成)之后,如果要再次将~/.bash_profile任何更改反映到整个环境中,则重新运行launchctl load ...命令将无法执行您想要的操作;相反,您会收到类似以下的警告:

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

为了重新加载环境变量,而无需执行注销 / 登录过程,请执行以下操作:

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

最后,请确保您重新启动已经运行的应用程序(包括 Terminal.app),以使他们知道所做的更改。

我还将代码和说明推到了 GitHub 项目osx-env-sync

我希望这将是最终的解决方案,至少对于最新版本的 OS X(Yosemite 和 El Capitan)而言。

  1. 做:

    vim ~/.bash_profile

    该文件可能不存在(如果不存在,则可以创建它)。

  2. 输入以下内容并保存文件:

    export PATH=$PATH:YOUR_PATH_HERE
  3. source ~/.bash_profile

在 OS X 中处理环境变量时,基本上有两个问题需要解决。第一个问题是从 Spotlight 调用程序(Mac 菜单 / 状态栏右侧的放大镜图标),第二个问题是从 Dock 调用程序。 。从终端应用程序 / 实用程序调用程序很简单,因为它从标准外壳程序位置( ~/.profile~/.bash_profile~/.bashrc等)读取环境。

从 Dock 调用程序时,请使用~/.MacOSX/environment.plist ,其中<dict>元素包含一系列<key>KEY</key><string>theValue</string>元素。

从 Spotlight 调用程序时,请确保已使用所需的所有键 / 值设置来设置启动程序。

为了同时解决这两个问题,我在用户帐户上使用了登录项(通过 “系统偏好设置” 工具设置)。登录项目是一个 bash 脚本,它调用 Emacs lisp 函数,尽管当然可以使用他们喜欢的脚本工具来完成相同的事情。这种方法的额外好处是它可以随时工作,并且不需要重新启动,即,可以编辑~/.profile ,在某些 shell 中运行登录项,并可以从 Dock 或 Dock 看到新调用程序的更改。聚光灯。

细节:

登录项目: ~/bin/macosx-startup

#!/bin/bash
bash -l -c "/Applications/Emacs.app/Contents/MacOS/Emacs --batch -l ~/lib/emacs/elisp/macosx/environment-support.el -f generate-environment"

Emacs Lisp 功能: ~/lib/emacs/elisp/macosx/envionment-support.el

;;; Provide support for the environment on Mac OS X

(defun generate-environment ()
  "Dump the current environment into the ~/.MacOSX/environment.plist file."
  ;; The system environment is found in the global variable:
  ;; 'initial-environment' as a list of "KEY=VALUE" pairs.
  (let ((list initial-environment)
        pair start command key value)
    ;; clear out the current environment settings
    (find-file "~/.MacOSX/environment.plist")
    (goto-char (point-min))
    (setq start (search-forward "<dict>\n"))
    (search-forward "</dict>")
    (beginning-of-line)
    (delete-region start (point))
    (while list
      (setq pair (split-string (car list) "=")
            list (cdr list))
      (setq key (nth 0 pair)
            value (nth 1 pair))
      (insert "  <key>" key "</key>\n")
      (insert "  <string>" value "</string>\n")

      ;; Enable this variable in launchd
      (setq command (format "launchctl setenv %s \"%s\"" key value))
      (shell-command command))
    ;; Save the buffer.
    (save-buffer)))

注意:此解决方案是在我添加我的解决方案之前合并而成的,尤其是 Matt Curtis 提供的解决方案,但我故意尝试使~/.bash_profile内容平台保持独立,并设置launchd环境的设置(仅 Mac 设施) )转换成单独的脚本。

EnvPane 是另一个免费的开源 Mac OS X v10.8(Mountain Lion)首选项窗格/environment.plist解决方案。

EnvPane 的源代码可在GitHub 上获得 。 EnvPane 看起来具有与RCEnvironment类似的功能,但是,它似乎可以立即更新其存储的变量,即不需要重新启动或登录,这是受欢迎的。

如开发商所说:

EnvPane 是 Mac OS X 10.8(Mountain Lion)的首选项窗格,可让您为图形会话和终端会话中的所有程序设置环境变量。它不仅可以恢复对 Mountain Lion 中〜/ .MacOSX / environment.plist 的支持,而且还可以立即发布对环境的更改,而无需注销并重新登录。 EnvPane 包括(并自动安装)已启动的代理程序,该代理程序将在 1)登录后及 2)每当〜/ .MacOSX / environment.plist 更改时运行。该代理读取〜/ .MacOSX / environment.plist,并通过与 launchctl setenv 和 launchctl unsetenv 相同的 API 将环境变量从该文件导出到当前用户的启动实例。

免责声明:我与开发人员或其项目无关。

PS 我喜欢这个名字(听起来像 “Ends Pain”)。

在 Mountain Lion 上,所有的/etc/paths/etc/launchd.conf编辑都不会起作用!

苹果的开发者论坛说:

“更改. app 本身的 Info.plist,使其包含具有所需环境变量的 “ LSEnvironment” 字典。

〜/ .MacOSX / environment.plist 不再受支持。”

因此,我直接编辑了应用程序的Info.plist (右键单击 “AppName.app”(在本例中为 SourceTree),然后单击 “ Show package contents ”)。

显示包装内容

我添加了一个新的键 / 字典对:

<key>LSEnvironment</key>
<dict>
     <key>PATH</key>
     <string>/Users/flori/.rvm/gems/ruby-1.9.3-p362/bin:/Users/flori/.rvm/gems/ruby-1.9.3-p362@global/bin:/Users/flori/.rvm/rubies/ruby-1.9.3-p326/bin:/Users/flori/.rvm/bin:/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:</string>
</dict>

(请参阅: Apple 的 LaunchServicesKeys 文档

在此处输入图片说明

现在,应用程序(在我的情况下为 Sourcetree)使用给定的路径并与 Git 1.9.3 一起使用:-)

PS:当然,您必须调整 Path 条目以适合您的特定路径需求。

更新(2017-08-04)

从(至少)macOS 10.12.6(Sierra)开始,此方法似乎已停止对 Apache httpd 起作用(对于systemlaunchctl configuser选项)。其他程序似乎没有受到影响。可以想象这是 httpd 中的错误。

原始答案

这涉及 OS X 10.10+(10.11+,特别是由于无根模式,其中/usr/bin不再可写)。

我已经在多个地方读到,由于 OS X 中的错误,使用launchctl setenv PATH <new path>设置PATH变量不起作用(从个人经验来看这是事实)。我发现还有另一种方法可以为未从 shell 启动的应用程序设置PATH

sudo launchctl config user path <new path>

该选项记录在 launchctl 手册页中:

配置系统 | 用户参数值

设置 launchd(8)域的持久配置信息。只能配置系统域和用户域。持久性存储的位置是实现细节,并且只能通过此子命令对该存储进行更改。需要重新引导才能使通过此子命令所做的更改生效。

[...]

路径

将目标域内所有服务的 PATH 环境变量设置为字符串值。字符串值应符合 environ(7)中 PATH 环境变量概述的格式。请注意,如果服务指定其自己的 PATH,则特定于服务的环境变量将具有优先权。

注意:此功能不能用于为域内的所有服务设置常规环境变量。它是有意限制 PATH 环境变量的范围,出于安全考虑,别无其他。

我已经确认这可以与从 Finder(使用getenv获取 PATH)启动的 GUI 应用程序一起使用。请注意,您只需要执行一次,更改将通过重新启动保持不变。

有时,所有先前的答案都根本无效。如果您想在 Eclipse 或 IntelliJ IDEA 中访问系统变量(例如M2_HOME ),那么在这种情况下唯一适合我的方法是:

首先(步骤 1)编辑/etc/launchd.conf以包含如下一行:“setenv VAR value”,然后(步骤 2)重新启动。

仅仅修改. bash_profile 是行不通的,因为在 OS X 中,应用程序无法像在其他 Unix 中那样启动。它们不继承父级的 shell 变量。所有其他修改由于我不知道的原因而无法使用。也许其他人可以对此进行澄清。