Установка переменных среды через launchd.conf больше не работает в OS X Yosemite / El Capitan / macOS Sierra / Mojave?

190

Похоже, что launchd.confбольше не загружает мою переменную окружения. Кто-нибудь еще заметил это?

Есть ли другое решение для постоянной установки переменных среды?

вздор
источник
Это работает и делает себя доступным в приложении, но не в терминале
Чанг Чжао

Ответы:

159

Создайте environment.plistфайл ~/Library/LaunchAgents/с этим содержимым:

<?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>

Вы можете добавить много launchctlкоманд внутри <string></string>блока.

plistАктивируется после перезагрузки системы. Вы также можете использовать launchctl load ~/Library/LaunchAgents/environment.plistего для немедленного запуска.

[Редактировать]

Такое же решение работает и в El Capitan.

Xcode 7.0+ не оценивает переменные окружения по умолчанию. Старое поведение можно включить с помощью этой команды:

defaults write com.apple.dt.Xcode UseSanitizedBuildSystemEnvironment -bool NO

[Редактировать]

Есть пара ситуаций, когда это не совсем работает. Если компьютер будет перезагружен и выбрано «Повторно открывать окна при повторном входе в систему», вновь открытые окна могут не видеть переменные (возможно, они открываются до запуска агента). Кроме того, если вы войдете через ssh, переменные не будут установлены (поэтому вам нужно будет установить их в ~ / .bash_profile). Наконец, это не работает для PATH в Эль-Капитане и Сьерре. Это должно быть установлено через 'launchctl config user path ...' и в / etc / paths.

MortimerGoro
источник
20
Нет необходимости перезагружаться! Вы можете сделать "launchctl start environment.plist" и перезапустить приложение, которое вам нужно, чтобы получить новые env vars;)
hasvn
1
Это не будет работать с переменной PATH для меня. Поэтому в дополнение к этому подходу для установки других переменных я установил переменную PATH в моем ~ / .bash_profile. Это может не сработать для каждого случая, но пока у меня нет проблем.
djule5
6
Разобрался: для работы без перезагрузки, это должен быть «launchctl load environment.plist», а не запуск
Дейв Хартнолл
2
О да. Ничего подобного неясным настройкам конфигурации, которые появляются ровно 9 раз во всем Интернете (Google UseSanitizedBuildSystemEnvironment).
Охад Шнайдер
2
Работает и на Сьерра
Shwouchk
64

[ Исходный ответ ]: Вы все еще можете использовать launchctl setenv variablename valueдля установки переменной, так чтобы она воспринималась всеми приложениями (графические приложения запускаются через Dock или Spotlight, в дополнение к тем, которые запускаются через терминал).

Очевидно, вы не захотите делать это каждый раз, когда вы входите в систему.

[ Изменить ]: Чтобы избежать этого, запустите AppleScript Editor, введите команду, подобную этой:

do shell script "launchctl setenv variablename value"

(Используйте несколько строк, если вы хотите установить несколько переменных)

Теперь сохраните ( + s) как Формат файла: Приложение . Наконец, откройте System SettingsПользователи и группыЭлементы входа и добавьте новое приложение.

[ Оригинальный ответ ]: Чтобы обойти это место, разместите все переменные, которые вы хотите определить в коротком скрипте оболочки, а затем взгляните на этот предыдущий ответ о том, как запустить скрипт при входе в MacOS . Таким образом, скрипт будет вызываться при входе пользователя в систему.

[ Редактировать ]: Ни одно из решений не является идеальным, поскольку переменные будут установлены только для этого конкретного пользователя, но я надеюсь / думаю, что это может быть все, что вам нужно.

Если у вас есть несколько пользователей, вы можете вручную установить элемент входа в систему для каждого из них или поместить копию com.user.loginscript.plist в каждый из своих локальных каталогов Library / LaunchAgents , указывая на один и тот же сценарий оболочки.

Конечно, ни один из этих обходных путей не так удобен, как /etc/launchd.conf .

[ Дальнейшее редактирование ]: пользователь ниже упоминает, что это не сработало для него. Однако я проверил на нескольких машинах Yosemite, и это работает для меня. Если у вас возникли проблемы, помните, что вам нужно будет перезапустить приложения, чтобы это вступило в силу. Кроме того, если вы устанавливаете переменные в терминале через ~ / .profile или ~ / .bash_profile , они будут переопределять настройки, установленные через launchctl setenv для приложений, запускаемых из оболочки .

ruario
источник
5
Насколько я могу судить, одним из недостатков этого метода является то, что переменные не будут установлены для любых других приложений, запускаемых при входе в систему. Так, например, если вы откроете Терминал, переменная будет установлена, но если вы выйдете из системы и снова
войдете в
Я попробовал это решение, и оно не сработало для меня. Но я специально ожидаю, что моя Java IDE (IntelliJ) подберет мои модификации пути, и это не так. Все отлично работает с терминала. Это может быть ошибка в IntelliJ. Все еще расстраивает то, что Apple удалила эту функциональность. Я позвонил в Apple, и они не очень помогли.
Джейсон
Это работает для меня, но знаете ли вы, что нужно сделать, чтобы также добавить переменные окружения в sudo?
etiennenoel
2
В целом это будет работать, однако в Yosemite есть ошибка (по крайней мере, 10.10.0 и 10.10.1), где настройка $ PATH не работает таким образом. Apple знает об ошибке. В настоящее время (по состоянию на 10.10.1) не существует известного способа установки общесистемного $ PATH для приложений с графическим интерфейсом.
TJ Luoma
3
После того, как вы воспользуетесь одним из вышеперечисленных способов и перезагрузите свой ноутбук - убедитесь, что вы явно повторно открываете приложения (такие как iTerm, терминал, Eclipse, IDEA или все, что вы используете). Если вы явно не перезапускаете их и если при перезагрузке OSx был установлен флажок «Перезапускать окна при повторном входе в систему» ​​(который используется по умолчанию) - эти программы не будут читать свежие переменные среды.
Ран
21

В Mac OS X 10.10 Yosemite можно установить переменные окружения с помощью 3 файлов + 2 команды.

Основной файл с определением переменных среды:

$ 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

Что мы получаем:

  1. Единственное место, где можно объявить системные переменные окружения: / etc / environment
  2. Мгновенное автоматическое обновление переменных среды после изменения файла / etc / environment - просто перезапустите приложение

Проблемы / проблемы:

Для того чтобы ваши переменные env были правильно приняты приложениями после перезагрузки системы, вам потребуется:

  • либо войдите дважды: login => logout => login
  • или закройте и снова откройте приложения вручную, где должны быть взяты переменные env
  • или НЕ используйте функцию «Открыть окна при входе в систему».

Это происходит из-за того, что Apple запрещает явное упорядочение загруженных сервисов, поэтому переменные env регистрируются параллельно с обработкой «очереди повторного открытия».

Но на самом деле, я перезагружаю свою систему только несколько раз в год (при больших обновлениях), так что это не имеет большого значения.

Ursa
источник
Отличная идея. Я попробовал это, и это работает для большинства переменных среды (например JAVA_HOME), но не для PATHпеременной (см. Мой вопрос о том, чтобы спросить другое ).
Halloleo
4
PATH должен быть установлен с помощью файла / etc / paths. Просто добавьте свой собственный путь в конец этого файла.
Ursa
Я не очень знаком с launchd, но разве нельзя было бы загрузить эти демоны при загрузке (т.е. до входа в систему)? Это должно обойти все проблемы, которые вы упоминаете.
Эгон
Мне нравится описанный выше подход, но у меня есть странная проблема, с которой нужно справиться. После перезагрузки genet VARNAME возвращает мне правильное значение, но echo $ VARNAME ничего не возвращает. Что может быть причиной этого? Я также опубликовал это на stackoverflow.com/questions/27045137/… и надеюсь, что у кого-нибудь здесь есть идея
ctp
Убедитесь, что права доступа к файлу / etc / environment соответствуют описанным выше.
imanuelcostigan
6

Цитируется из

Apple Developer Relations 10-Oct-2014 09:12 PM

После долгих размышлений инженерия удалила эту функцию. Файл /etc/launchd.confбыл намеренно удален по соображениям безопасности. В качестве обходного пути вы можете запускать launchctl limitс правами root в начале загрузки, возможно, из LaunchDaemon. (...)

Решение:

Поместите код в /Library/LaunchDaemons/com.apple.launchd.limit.plistbash-скрипт:

#!/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
а
источник
1
Можете ли вы объяснить это немного больше? Я не вижу, как «Решить проблему» относится к первоначальной проблеме!
Ник H247
Не OP, но я думаю, что суть здесь такова: поместите этот список в список /Library/LaunchDaemons, и вместо того, launchctlчтобы указывать запускать limitкоманду, скажите ему выполнить setenvкоманду с PATHуказанием строки пути в качестве аргументов. launchdдолжен автоматически поднять его при запуске и сразу же получить видоизменения.
Лейрд Нельсон
5
XML не полностью скопирован. Строка Doctype должна читаться<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
UloPe
6
@aax, какая часть этого списка фактически устанавливает переменную окружения?
HairOfTheDog
3

Вот команды для восстановления старого поведения:

# 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

Теперь вы можете указать команды, как setenv JAVA_HOME /Library/Java/Homeв /etc/launchd.conf.

Проверено на Эль Капитане.

Янченко
источник
2

Что сработало для меня (вдохновлено благодарностью 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

Я надеюсь, что это помогло вам.

Батист
источник
10
Какое отношение это решение имеет к настройке переменных среды?
HairOfTheDog
2

Вы можете попробовать https://github.com/ersiner/osx-env-sync . Он обрабатывает как приложения командной строки, так и приложения с графическим интерфейсом из одного источника и работает с последней версией OS X (Yosemite).

Вы можете использовать подстановки путей и другие хитрости оболочки, поскольку то, что вы пишете, - это обычный bash-скрипт, который в первую очередь использует bash. Без ограничений. (Проверьте документацию osx-env-sync, и вы поймете, как это достигается.)

Я ответил на аналогичный вопрос здесь, где вы найдете больше.

Эрсин Эр
источник
-3

Решение состоит в том, чтобы добавить вашу переменную в /etc/profile. Тогда все работает как положено! Конечно, вы ДОЛЖНЫ сделать это как пользователь root с помощью sudo nano / etc / profile. Если вы отредактируете его любым другим способом, система будет жаловаться на поврежденный профиль / etc /, даже если вы измените права доступа на root.

Илиас
источник
7
Добавление переменных окружения в профиль значительно уступает, так как влияет только на процессы оболочки.
UloPe
-5

Я добавил переменные в ~ / .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
Робин
источник
Обратите внимание, что вам не нужно выходить из системы и обратно. Просто используйте команду source, то есть source .bash_profile.
Майкл
2
Кроме того, проблема этого метода заключается в том, что вам еще нужно открыть терминал, прежде чем станут доступны переменные среды. Лучше сделать то, что есть в первом ответе, чтобы они были доступны без необходимости открывать терминал.
Майкл
1
Это не работает на приложениях, загруженных через SpotLight. stackoverflow.com/questions/135688/…
Расика Перера
1
Использование конфигурационных файлов bash имеет ограниченную помощь, поскольку предполагает, что вы всегда получаете bash в качестве предка процесса, который окружает вас. Spotlight, finder, emacs, xcode, cronjobs, агенты запуска, любая IDE, браузеры контроля версий и т. Д. И т. Д. Не будут иметь bash в качестве предка. Единственный процесс, который может охватить их последовательно, запускается.
Бен Хайд