Вопрос или проблема
Ранее я думал, что переменные окружения определяются в области процесса, и если они экспортируются, то передаются дочерним процессам.
Таким образом, я хотел найти единственное место для определения моих переменных окружения и чтобы они были доступны для:
- Сервиса пользователя, определенного в ~/.config/systemd/user/start-up.service
- Файла hyprland.conf
- Оболочки ZSH
Я использую Arch Linux с SDDM, Hyprland, терминалом Kitty и оболочкой ZSH. Я попробовал несколько решений, и единственным работающим был вариант определения переменных окружения в файле hyprland.conf (на самом деле, во внешнем файле, подключаемом Hyprland), и иметь дублирующее определение для двух переменных окружения, необходимых сервису, в поле Environment сервиса. Я не могу использовать EnvironmentFile, так как между форматами, ожидаемыми Hyprland и файлами сервисов, существует несоответствие. Мне не нравится это решение из-за дублирования.
Но в процессе моего исследования я обнаружил очень неожиданную вещь: все переменные окружения, определенные в hyprland.conf, видны в оболочке ZSH, хотя оболочка не является дочерним процессом Hyprland.
pstree
systemd─┬─NetworkManager───4*[{NetworkManager}]
├─dbus-daemon
==> ├─kitty─┬─zsh───pstree
│ └─2*[{kitty}]
├─polkitd───3*[{polkitd}]
├─rtkit-daemon───2*[{rtkit-daemon}]
├─sddm─┬─Xorg───2*[{Xorg}]
==> │ ├─sddm-helper───Hyprland───4*[{Hyprland}]
│ └─{sddm}
├─sh───sleep
├─ssh-agent
├─systemd─┬─(sd-pam)
│ ├─dbus-daemon
│ ├─gnome-keyring-d───4*[{gnome-keyring-d}]
│ ├─pipewire───2*[{pipewire}]
│ ├─pipewire-pulse───2*[{pipewire-pulse}]
│ ├─wireplumber───6*[{wireplumber}]
│ ├─2*[xdg-desktop-por───4*[{xdg-desktop-por}]]
│ ├─xdg-document-po─┬─fusermount3
│ │ └─6*[{xdg-document-po}]
│ └─xdg-permission-───3*[{xdg-permission-}]
├─systemd-journal
├─systemd-logind
├─systemd-timesyn───{systemd-timesyn}
├─systemd-udevd
├─upowerd───3*[{upowerd}]
└─wpa_supplicant
Таким образом, у меня на самом деле два вопроса:
- Существует ли единственное место для определения переменных окружения (которые должны определяться на уровне пользователя, а не системы), чтобы они были видны для сервиса пользователя, Hyprland и оболочки?
- Как возможно, что переменные, определенные в hyprland.conf, видны его дочернему процессу?
Я наткнулся на этот вопрос, пытаясь разобраться с настройкой PATH
в swaywm, поэтому думаю, что наши мотивы схожи. Я не являюсь экспертом в POSIX или C, но вот что я думаю после прочтения соответствующих страниц руководства и исходного кода GLIBC (поправки приветствуются):
-
“Окружение” – это строка специфичная для каждого процесса. Вы можете узнать, с чем процесс был создан из
/proc/(pid)/environ
, но это не означает, что строка не была изменена с тех пор. -
Когда программа использует GLIBC, новые процессы инициируются с помощью семейства функций C
exec
. Некоторые из них неявно копируют переменнуюenviron
для новых процессов, некоторые позволяют передать новую в качестве аргумента (например,execle
и т.д.). С этого момента два процесса не разделяют окружение. Таким образом, дочерний процесс может получить окружение родительского процесса, но после этого, если родитель изменяет свое собственное (например, с помощьюsetenv
), окружение дочернего процесса останется неизменным. -
В Unix/Linux нет “глобального окружения”. Это просто процессы, передающие спецификации окружения своим детям. Существуют механизмы для чтения переменных окружения в определенный момент (например, см. вики Arch), но это всего лишь соглашения.
-
Оболочки ведут список переменных, который отличается от их
environ
. В большинстве оболочекexport FOO
просто означает “добавить FOO кenviron
при запуске новых процессов.”
Я предполагаю, что переменные окружения, попадающие в вашу zsh, не исходят из непарентного процесса, а могут быть результатом предыдущей попытки конфигурации, о которой вы могли забыть.
Ответ или решение
Область применения переменных окружения в Linux
Переменные окружения играют ключевую роль в конфигурации процессов и управлении настройками в операционных системах на базе Unix/Linux. Понимание их области применения и способа работы может значительно упростить администрирование системы. В этой статье мы рассмотрим два основных вопроса, связанные с переменными окружения, заданные в контексте использования Arch Linux с графическим окружением Hyprland и оболочкой Zsh.
1. Единственное место определения переменных окружения
Для достижения цели создания единой точки определения переменных окружения, которая будет доступна как для пользовательских сервисов systemd, так и для всех процессов, запущенных в частности графическим окружением и оболочкой, существует несколько вариантов:
-
Использование файлов конфигурации:
Переменные окружения можно определять в различных файлах конфигурации, таких как~/.bashrc
,~/.zshrc
или даже в.profile
. Эти файлы выполняются при запуске соответствующей оболочки и могут содержать командыexport VAR_NAME=value
, что сделает переменные доступными для всех дочерних процессов. -
Конфигурация в системных файлах:
В некоторых случаях имеет смысл использовать файл~/.config/environment
, который автоматически считывается графическими окружениями, или определять переменные в конфигурационных файлах самих системных демонов, таких как злободневные.desktop
файлы в директории~/.config/autostart/
. -
Системные средства управления окружением:
Некоторые пользователи предпочитают использовать такие инструменты, какenv
,setenv
, или специализированные скрипты для задания окружения, которые затем вызываются на старте сессии.
Заметьте, что переменные, указанные в сервисных единицах systemd, могут быть указаны непосредственно в файле службы (например, в Environment=
), однако, учитывая вашу ситуацию с Hyprland, надо быть осторожным из-за несоответствий форматов.
2. Видимость переменных окружения в оболочке Zsh
Вы удивлены тем, что переменные, определенные в файле конфигурации Hyprland, видны в Zsh, несмотря на то, что Zsh не является дочерним процессом Hyprland. Это может происходить по нескольким причинам:
-
Наследование переменных окружения:
Elementy окружения могут быть определены в одноименных файлах конфигурации, которые загружаются на уровне сессии. Например, если файл конфигурации Hyprland инициализирует окружение во время старта сессии, это может оказать влияние на общие параметры окружения. -
Передача во время инициализации:
Когда Hyprland запускается, он может инициировать сессию, при этом экспортируя переменные окружения в контекст системы. Sixube, в этом случае Zsh может получить доступ к этим переменным, поскольку они были установлены на этапе инициализации рабочего окружения. -
Конфигурация единого окружения:
Ваша система может использовать унифицированный менеджер сессий, который обрабатывает и передает переменные окружения через общие методы, такие как D-Bus или другие слои абстракции. Это позволяет такие параметры какPATH
,EDITOR
, и другие переменные быть доступными для всех клиентов.
Заключение
Решение описанных вами вопросов является частью более широкой проблемы управления окружением в Linux. Ключевой вывод состоит в том, что хотя переменные окружения могут определяться локально для каждого процесса, существуют механизмы, позволяющие им быть доступными шире, чем вы могли ожидать. Если вам необходимо добиться консистентности и избежать дублирования, рекомендуется изучить способ глобального или пользовательского управления переменными окружения, а также проверить, какие файлы конфигурации и скрипты выполняются в вашей системе.
Для всестороннего управления окружением создайте обобщенный файл конфигурации или используйте системные утилиты, чтобы гарантировать, что все нужные переменные будут доступны для ваших сервисов и оболочек без дублирования.