Перманентно выставить переменные в Mac OS - нетривиальная задача. По задумке, такие переменные пользователю не нужны, а значит максимум, где их можно выставить - это в ~.zshrc. На практике же есть и другие способы выставить переменные, в том числе на уровне всех пользователских процессов.

Но рассказать что и как прям сразу - это же не интересно, читателя надо помучать. Итак, начнём издалека.

Всё что ни делается в Mac OS - делается от имени пользователя. Предполагается, что это для нашей же, пользовательской, безопасности. Дело доходит до того, что раздел с основной системой монтируется в режиме read-only. То есть внести изменения в процесс загрузки, в список запущенных системных сервисов итд итп... невозможно.

И, как полагается, существует масса процессов и сервисов, которые впустую расходуют ресурсы системы и которые естественно просто так не отключишь - с каждым новым релизом добавляются новые "шпильки" в процесс монтирования корневого раздела в режиме rw и в процесс изменения его содержимого. Но это всё лирика и мы отошли от темы слишком далеко. Нам достаточно знать, что изменения "глобального" характера в Mac OS - это всегда изменения на уровне настроек конкретного пользователя.

Итак, с интрой закончили, перейдём поближе к телу.

Если погуглить сабж, то интернеты будут полны советами, "как прописать переменную в ~/.bash_profile". Ясен-красен, что это всё индусская копи-паста сведений примерно года 2019, октября месяца или около того. Именно тогда была выпущена Catalina (10.15). Кстати, это был последний релиз Mac Os X (то есть, 10-й версии системы), за ней последовал Big Sur (11-я версия), которая впервые заподдерживала процессоры apple silicon, на архитектуре aarch64. Так вот, именно в Catalina zsh сменил на посту default-ного shell-а bash... В более продвинутых советах предлагают ставить переменную в ~/.zshrc. Все эти советы работают только для консоли, ибо в интерактивном режиме shell-ы загружают означенные файлы, фактически выполняя все даденные команды перед тем, как передать управление пользователю. Но есть один нюанс - эти файлы не исполняются в режиме без терминала, то есть в обычной GUI наши переменные окружения не будут заданы.

Задать переменные окружения как глобальные, так и для всей сессии пользователя можно и в linux-е и в windows-е, там это тривиальное действие. А вот в Mac OS придётся немного поломать голову, потому что... задание переменной - это фактически запуск сервиса! Кто бы мог подумать, правда?

Пользовательский сервис - это агент, его можно создать, создав файл, описывающий что надо сделать системе инициализации сервисов в Mac OS - launchctl.

Например, мы хотим задать параметры управления памятью для nodejs, что мы делаем? - создаём файл ~/Library/LaunchAgents/setenv.NODE_OPTIONS.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>setenv.NODE_OPTIONS</string>
    <key>ProgramArguments</key>
    <array>
        <string>/usr/bin/env</string>
        <string>NODE_OPTIONS=--max-old-space-size=3072 --max-semi-space-size=512</string>
        <string>launchctl</string>
        <string>setenv</string>
        <string>NODE_OPTIONS</string>
        <string>--max-old-space-size=3072 --max-semi-space-size=512</string>
    </array>
    <key>RunAtLoad</key>
    <true/>
</dict>
</plist>

И это пропишет переменные окружения для всей пользовательской сессии.

По сути, весь этот опус был написан ради последних пары абзацев. Ну и ради бугурта по поводу вендор-лока, потому что это не про безопасность пользователя, а про безопасность больших компаний от действий пользователя, про навязывание ему чего-то, без возможности это "чего-то" заменить или убрать на стороне пользователя.

Next Post