看起来 launchd.conf
不再加载我的环境变量。有没有其他人注意到这一点?
是否有另一种永久设置环境变量的解决方案?
在 ~/Library/LaunchAgents/
中使用以下内容创建一个 environment.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>my.startup</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>-c</string>
<string>
launchctl setenv PRODUCTS_PATH /Users/mortimer/Projects/my_products
launchctl setenv ANDROID_NDK_HOME /Applications/android-ndk
launchctl setenv PATH $PATH:/Applications/gradle/bin
</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
您可以在 <string></string>
块内添加许多 launchctl
命令。
plist
将在系统重新启动后激活。您也可以使用 launchctl load ~/Library/LaunchAgents/environment.plist
立即启动它。
[编辑]
同样的解决方案也适用于 El Capitan。
Xcode 7.0+ 默认不评估环境变量。可以使用以下命令启用旧行为:
defaults write com.apple.dt.Xcode UseSanitizedBuildSystemEnvironment -bool NO
[编辑]
在某些情况下,这并不完全奏效。如果重新启动计算机并选择“重新登录时重新打开窗口”,重新打开的窗口可能看不到变量(可能在代理运行之前打开它们)。此外,如果您通过 ssh 登录,则不会设置变量(因此您需要在 ~/.bash_profile 中设置它们)。最后,这似乎不适用于 El Capitan 和 Sierra 上的 PATH。这需要通过“launchctl config user path ...”和 /etc/paths.xml 进行设置。
[原始答案]:您仍然可以使用 launchctl setenv variablename value
设置一个变量,以便所有应用程序(此外,通过 Dock 或 Spotlight 启动的图形应用程序到那些通过终端启动的人)。
显然,您不会希望每次登录时都这样做。
[编辑]:为避免这种情况,启动 AppleScript Editor
,输入如下命令:
do shell script "launchctl setenv variablename value"
(如果要设置多个变量,请使用多行)
现在将 (⌘
+s
) 保存为文件格式:应用程序。最后打开 System Settings
→ Users &组 → 登录项 并添加您的新应用程序。
[原始答案]:要解决您希望在简短的 shell 脚本中定义的所有变量,请查看此 previous answer about how to run a script on MacOS login。这样,当用户登录时脚本将被调用。
[编辑]:这两种解决方案都不是完美的,因为变量只会为该特定用户设置,但我希望/猜测这可能是您所需要的。
如果您确实有多个用户,您可以为每个用户手动设置一个登录项,或者将 com.user.loginscript.plist 的副本放在他们的每个本地 Library/LaunchAgents 目录中,指向同一个 shell 脚本。
当然,这些变通方法都没有 /etc/launchd.conf 方便。
[进一步编辑]:下面的用户提到这对他不起作用。但是,我已经在多台 Yosemite 机器上进行了测试,它确实对我有用。如果您遇到问题,请记住您需要重新启动应用程序才能使其生效。此外,如果您通过 ~/.profile 或 ~/.bash_profile 在终端中设置变量,它们将覆盖通过 launchctl setenv 为从 shell 启动的应用程序设置的内容。
可以使用 3 个文件 + 2 个命令在 Mac OS X 10.10 Yosemite 上设置环境变量。
带有环境变量定义的主文件:
$ ls -la /etc/environment
-r-xr-xr-x 1 root wheel 369 Oct 21 04:42 /etc/environment
$ cat /etc/environment
#!/bin/sh
set -e
syslog -s -l warn "Set environment variables with /etc/environment $(whoami) - start"
launchctl setenv JAVA_HOME /usr/local/jdk1.7
launchctl setenv MAVEN_HOME /opt/local/share/java/maven3
if [ -x /usr/libexec/path_helper ]; then
export PATH=""
eval `/usr/libexec/path_helper -s`
launchctl setenv PATH $PATH
fi
osascript -e 'tell app "Dock" to quit'
syslog -s -l warn "Set environment variables with /etc/environment $(whoami) - complete"
为用户应用程序(终端、IDE、...)加载环境变量的服务定义:
$ ls -la /Library/LaunchAgents/environment.user.plist
-rw------- 1 root wheel 504 Oct 21 04:37 /Library/LaunchAgents/environment.user.plist
$ sudo cat /Library/LaunchAgents/environment.user.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>environment.user</string>
<key>ProgramArguments</key>
<array>
<string>/etc/environment</string>
</array>
<key>KeepAlive</key>
<false/>
<key>RunAtLoad</key>
<true/>
<key>WatchPaths</key>
<array>
<string>/etc/environment</string>
</array>
</dict>
</plist>
root 用户应用程序的相同服务定义:
$ ls -la /Library/LaunchDaemons/environment.plist
-rw------- 1 root wheel 499 Oct 21 04:38 /Library/LaunchDaemons/environment.plist
$ sudo cat /Library/LaunchDaemons/environment.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>environment</string>
<key>ProgramArguments</key>
<array>
<string>/etc/environment</string>
</array>
<key>KeepAlive</key>
<false/>
<key>RunAtLoad</key>
<true/>
<key>WatchPaths</key>
<array>
<string>/etc/environment</string>
</array>
</dict>
</plist>
最后我们应该注册这些服务:
$ launchctl load -w /Library/LaunchAgents/environment.user.plist
$ sudo launchctl load -w /Library/LaunchDaemons/environment.plist
我们得到什么:
唯一声明系统环境变量的地方: /etc/environment 修改 /etc/environment 文件后即时自动更新环境变量 - 只需重新启动您的应用程序
问题/问题:
为了在系统重新启动后应用程序正确获取您的环境变量,您将需要:
要么登录两次:登录=>注销=>登录
或手动关闭并重新打开应用程序,其中应采用环境变量
或者不要使用“重新登录时重新打开窗口”功能。
发生这种情况是因为 Apple 拒绝对加载的服务进行显式排序,因此 env 变量与“重新打开队列”的处理并行注册。
但实际上,我每年只重启几次系统(大更新),所以这没什么大不了的。
launchd
不是很熟悉,但难道不能在启动时(即登录前)加载这些守护进程吗?那应该绕过你提到的所有问题。
引自
Apple Developer Relations 10-Oct-2014 09:12 PM
经过深思熟虑,工程已删除此功能。出于安全原因,有意删除了文件 /etc/launchd.conf。作为一种解决方法,您可以在引导期间尽早以 root 身份运行 launchctl limit,可能来自 LaunchDaemon。 (...)
解决方案:
通过 bash-script 将代码放入 /Library/LaunchDaemons/com.apple.launchd.limit.plist:
#!/bin/bash
echo '<?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>eicar</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>limit</string>
<string>core</string>
<string>unlimited</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>' | sudo tee /Library/LaunchDaemons/com.apple.launchd.limit.plist
/Library/LaunchDaemons
,而不是告诉 launchctl
运行 limit
命令,而是告诉它运行带有 PATH
的 setenv
命令和路径字符串作为参数。 launchd
应该会在启动时自动获取并几乎立即进行自我修改。
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
以下是恢复旧行为的命令:
# create a script that calls launchctl iterating through /etc/launchd.conf
echo '#!/bin/sh
while read line || [[ -n $line ]] ; do launchctl $line ; done < /etc/launchd.conf;
' > /usr/local/bin/launchd.conf.sh
# make it executable
chmod +x /usr/local/bin/launchd.conf.sh
# launch the script at startup
echo '<?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>launchd.conf</string>
<key>ProgramArguments</key>
<array>
<string>sh</string>
<string>-c</string>
<string>/usr/local/bin/launchd.conf.sh</string>
</array>
<key>RunAtLoad</key>
<true/>
</dict>
</plist>
' > /Library/LaunchAgents/launchd.conf.plist
现在您可以在 /etc/launchd.conf
中指定类似 setenv JAVA_HOME /Library/Java/Home
的命令。
检查 El Capitan。
setenv
命令仅适用于调用者的上下文 - 所以这适用于 LaunchAgents,而 LaunchDaemons 需要一个单独的文件吗?
什么对我有用(灵感来自 aax' 谢谢):
将此粘贴到 /Library/LaunchDaemons/com.apple.launchd.limit.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>eicar</string>
<key>ProgramArguments</key>
<array>
<string>/bin/launchctl</string>
<string>limit</string>
<string>maxfiles</string>
<string>16384</string>
<string>16384</string>
</array>
<key>RunAtLoad</key>
<true/>
<key>ServiceIPC</key>
<false/>
</dict>
</plist>
如果您需要它一步一步:
启动终端
输入 sudo su 然后输入密码以 root 身份登录
输入 vi /Library/LaunchDaemons/com.apple.launchd.limit.plist
进入 vi 编辑器时,按 i 键进入插入模式,然后粘贴上面的确切代码内容 (⌘+v)。这将强制限制每个进程 16384 个文件,总共 16384 个文件
保存文件并使用 esc 退出,然后:wq
重新启动系统,并使用命令 launchctl limit 检查它是否正常工作
我希望这对你有所帮助。
您可以试一试https://github.com/ersiner/osx-env-sync。它从单一来源处理命令行和 GUI 应用程序,并与 最新版本的 OS X (Yosemite) 配合使用。
您可以使用路径替换和其他 shell 技巧,因为您编写的是首先由 bash 获取的常规 bash 脚本。没有限制..(查看 osx-env-sync 文档,您将了解它是如何实现这一点的。)
我回答了一个类似的问题here,您可以在其中找到更多信息。
解决方案是将变量添加到 /etc/profile
。然后一切都按预期工作!当然,您必须以 root 用户身份使用 sudo nano /etc/profile。如果您以任何其他方式对其进行编辑,即使您将权限更改为 root,系统也会抱怨 /etc/profile 损坏。
我通过以下方式在 ~/.bash_profile 中添加了变量。完成后重新启动/注销并登录
export M2_HOME=/Users/robin/softwares/apache-maven-3.2.3
export ANT_HOME=/Users/robin/softwares/apache-ant-1.9.4
launchctl setenv M2_HOME $M2_HOME
launchctl setenv ANT_HOME $ANT_HOME
export PATH=/usr/bin:/bin:/usr/sbin:/sbin:/usr/local/bin:/Users/robin/softwares/apache-maven-3.2.3/bin:/Users/robin/softwares/apache-ant-1.9.4/bin
launchctl setenv PATH $PATH
注意:无需重新启动/注销并登录,您可以使用以下方式应用这些更改;
source ~/.bash_profile
UseSanitizedBuildSystemEnvironment
)。sudo launchctl config user path $PATH
适用于 Mojave