Вернуться назад

Environment

Переменные shell

# Присваиваем переменной значение:
QT_QPA_PLATFORMTHEME=qt6ct

# проверяем:
echo QT_QPA_PLATFORMTHEME
  # qt6ct

Отлично. Всё работает.

То же самое можно сделать так:

# Присваиваем переменной значение:
env QT_QPA_PLATFORMTHEME=qt6ct

# проверяем:
echo QT_QPA_PLATFORMTHEME
  # qt6ct

Тоже всё работает. В bash команда env создаёт shell-переменную. В других шеллах эта команда может вести себя по-другому. Например, создавать environment-переменную. Но в bash два вышеприведённых примера эквивалентны.

Но если мы сейчас попробуем запустить Qt6-приложение (пусть это будет feather) в том же терминале таким вот образом:

featherpad

то обнаружим, что приложение не видит эту переменную.

Чтобы передать значение переменной программе, нужно сделать это в той же строке, где мы это приложение запускаем:

# либо так:
QT_QPA_PLATFORMTHEME=qt6ct featherpad

# либо так:
env QT_QPA_PLATFORMTHEME=qt6ct featherpad

Вот сейчас featherpad увидит переменную QT_QPA_PLATFORM и применит Qt-стиль, который указан в qt6ct.

Environment

Environment (окружение процесса) – это набор пар ИМЯ=ЗНАЧЕНИЕ, который передаётся каждому запущенному процессу при старте.

Посмотреть значения environment-переменных можно так:

# Посмотреть все переменные:
env

# Посмотреть значение конкретной переменной:
printenv XDG_SESSION_TYPE
# присваиваем значение переменной:
QT_QPA_PLATFORMTHEME=qt6ct

# выводим его:
echo $QT_QPA_PLATFORMTHEME
  # qt6ct

printenv QT_QPA_PLATFORMTHEME
  # ничего не вывелось

То есть тут мы присвоили значение переменной внутри нашего shell. Но shell-переменная ≠ environment-переменная. Поэтому если мы запустим featherpad без явной передачи переменной, то featherpad эту переменную не увидит.

Если мы хотим создать именно environment-переменную, то это делается так:

export QT_QPA_PLATFORMTHEME=qt6ct

# теперь мы можем проверить её:
printenv QT_QPA_PLATFORMTHEME
  # qt6ct

# и теперь можно запустить featherpad:
featherpad
  # стиль применился

.bashrc, .profile

Если я впишу в ~/.profile:

export QT_QPA_PLATFORMTHEME=qt6ct

... то переменная не попадёт в environment. Потому что я запускаю sway из shell'а и sway наследует environment текущего shell.

# Проверим, логин ли у меня shell:
shopt -q login_shell && echo LOGIN || echo NOT_LOGIN
  # NOT_LOGIN

# поэтому .profile не работает

Что читает bash в каждом случае

login-shell

обычный интерактивный shell

При логине bash читает ~/.bash_profile. Я могу выполнить скрипт ~/.profile внутри ~/.bash_profile:

# ~/.profile

export QT_QPA_PLATFORMTHEME=qt6ct
# ~/.bash_profile

source ~/.profile

Можно конечно объявить environment-переменную прямо в ~/.bash_profile, но ~/.profile + source – считается классическим UNIX-подходом.

Откуда PATH?

Если у меня не работают /etc/profile и ~/.profile, откуда тогда PATH? Ответ:

В современной Linux-системе environment – это продукт PAM + systemd, а shell – просто потребитель.

PAM подгружает модули из /etc/pam.d/login и /etc/pam.d/system-login.

# /etc/pam.d/system-login
# ...
session   optional   pam_env.so
session   required   pam_systemd.so
# ...

А сами значения приходят отсюда:

# /etc/login.defs
# ...
ENV_PATH        PATH=/usr/local/sbin:/usr/local/bin:/usr/bin
ENV_SUPATH     PATH=/usr/local/sbin:/usr/local/bin:/usr/bin:/usr/sbin:/usr/bin
# ...

Это и есть базовый PATH.

PAM

PAM – Pluggable Authentication Modules (Подключаемые модули аутентификации). Это слой между программой и системой, который решает: кто ты, можно ли тебя пустить и с какими условиями. Без PAM каждая программа должна была бы сама проверять пароль, настроивать сессию, задавать переменные. А с PAM всё это вынесено в единый механизм.

Как выглядит PAM на практике. Каждая программа имеет файл в /etc/pam.d/. Внутри – цепочка модулей.

login-shell

login-shell – это shell, запущенный с флагом --login. Только login-shell читает .profile.

Ещё один способ задать environment-переменную

Вариант 2. Рекомендуемый для Wayland (лучший): Использовать systemd user environment (я его советовал не случайно).

mkdir -p ~/.config/environment.d
nano ~/.config/environment.d/99-qt.conf
# ~/.config/environment.d/99-qt.conf

QT_QPA_PLATFORMTHEME=qt6ct

Но у меня этот способ не работает. Насколько я понял, у меня нет полноценной "systemd-user session". У меня сессия: TTY -> login -> bash (не login-shell) -> sway.

Проверить видит ли systemd переменную:

# Проверим systemd-user:
systemctl --user show-environment

# Можно проверить так:
systemctl --user show-environment

Как сделать полноценную session

1. Включить linger, чтобы user systemd жил независимо от логина:

loginctl enable-linger $USER

2. Перезагрузиться и заново войти в TTY

3. Проверить:

systemctl --user show-environment

Должны появиться переменные из ~/.config/environment.d/