Какой лучший способ установить переменные окружения в зависимости от дистрибутива / оболочки?

31

Вопрос говорит обо всем. В настоящее время я использую Arch Linux и zsh, но мне бы хотелось, чтобы решение, которое (как минимум) работало как на VT, так и на xterms, а также (надеюсь, желательно) продолжало бы работать, если я переключаю дистрибутивы или оболочки.

Я слышал дико разрозненные ответы на этот вопрос в разных документах дистрибутивов. Ubuntu говорит "использовать .pam_environment". Я думаю, в Arch, что они рекомендуют, зависит от вашей оболочки. В настоящее время я помещаю все в .profile и, если по какой-то причине оболочка не получает его (например, bash, если существует .bash_profile), я переопределяю это, используя его вручную. Но похоже, что должен быть лучший путь.

strugee
источник
2
Это не имеет ничего общего с дистрибутивом и все, что связано с оболочкой. Не уверен, что есть портативный способ сделать это, хотя.
Джозеф Р.
Хм. Круто .
13

Ответы:

29

К сожалению, нет полностью переносимого места для установки переменных среды. Два файла, которые наиболее близки ~/.profile, - это традиционное местоположение, которое работает во многих установках, и ~/.pam_environmentсовременная, распространенная, но ограниченная альтернатива.

Что положить в ~/.pam_environment

Файл ~/.pam_environmentчитается всеми методами входа в систему, которые используют PAM и у которых этот файл включен. Это охватывает большинство систем Linux в настоящее время.

Основным преимуществом ~/.pam_environmentявляется то, что (когда он включен) он читается до запуска оболочки пользователя, поэтому он работает независимо от типа сеанса, оболочки входа в систему и других сложностей. Это даже работает для неинтерактивных логинов, таких как su -c somecommandи ssh somecommand.

Основным ограничением ~/.pam_environmentявляется то, что вы можете размещать только простые назначения, а не сложный синтаксис оболочки. Синтаксис этого файла следующий.

  • Файлы анализируются построчно.
  • Ведущие пробелы игнорируются.
  • Вы можете по желанию начинать строки с exportодного пробела (не табуляция, иди рисунок).
  • После этого каждая строка должна иметь форму, в VAR=VALUEкоторой VAR состоит из букв, цифр и подчеркиваний.
  • # начинается комментарий, он не может появиться в значении.
  • Если VALUE начинается с 'или "и содержит другую идентичную кавычку, тогда VAR устанавливается на строку между кавычками (все, что находится после второй кавычки, игнорируется). В противном случае VAR устанавливается на строку после =знака.
  • Если нет =, переменная удаляется из среды.

Таким образом, ~/.pam_environmentс другой стороны, работает в большом количестве обстоятельств. С другой стороны, у вас не может быть никаких динамических настроек, таких как основание значения переменной на другой переменной (например, добавление каталога в PATH) или использование вывода команды (например, проверка наличия каталога или программы), а также некоторые символы ( #'", перевод строки) невозможно или затруднить в значении.

Что положить в ~/.profile

Этот файл должен иметь переносимый (POSIX) синтаксис sh. Используйте расширения ksh или bash (массивы [[ … ]]и т. Д.) Только в том случае, если вы знаете, что в вашей системе такие оболочки есть /bin/sh.

Этот файл может быть прочитан скриптами в автоматизированных приложениях, поэтому он не должен вызывать программы, которые производят какой-либо вывод или вызов exec. Если вы хотите сделать это при входе в текстовый режим, делайте это только для интерактивных оболочек. Пример:

case $- in *i*)
  # Display a message if I have new mail
  if mail -e; then echo 'You have new mail'; fi
  # If zsh is available, and this looks like a text-mode login, run zsh
  case "`ps $PPID` " in
    *" login "*)
      if type zsh >/dev/null 2>/dev/null; then exec zsh; fi;;
  esac
esac

Это пример использования /bin/shвашей оболочки входа в систему и переключения на вашу любимую оболочку. Смотрите также, как я могу использовать bash в качестве оболочки для входа в систему, когда мой системный администратор отказывается разрешить мне изменить его

Когда ~/.profileне читается при неграфическом входе в систему?

Различные логины читают разные файлы.

Если ваш логин оболочки bash

Bash читает ~/.bash_loginили, ~/.bash_profileесли они существуют вместо ~/.profile. Также bash не читает ~/.bashrcв логине, даже если он интерактивный. Чтобы никогда больше не запоминать эти причуды, создайте ~/.bash_profileстроку со следующими двумя строками:

. ~/.profile
case $- in *i*) . ~/.bashrc;; esac

См. Также Какие файлы установки следует использовать для настройки переменных среды с помощью bash?

Если ваш логин оболочки zsh

Зш читает ~/.zprofileи ~/.zlogin, но нет ~/.profile. Zsh имеет синтаксис, отличный от sh, но может читать ~/.profileв режиме эмуляции sh. Вы можете использовать это для ~/.zprofile:

emulate sh -c '. ~/.profile'

Смотрите также Zsh, не попадающий в ~ / .profile

Если ваша оболочка входа в систему является другой оболочкой

Там мало что можно сделать, за исключением использования в /bin/shкачестве оболочки для входа и вашей любимой оболочки (например, fish) только в качестве интерактивной оболочки. Вот что я делаю с Zsh. Смотрите выше пример вызова другой оболочки из ~/.profile.

Удаленные команды

При вызове удаленной команды без прохождения через интерактивную оболочку не все оболочки читают файл запуска.

Ksh читает файл, указанный в ENVпеременной, если вам удастся передать его.

Bash читает, ~/.bashrcесли он не интерактивный (!) И его родительский процесс вызывается rshdили sshd. Таким образом, вы можете начать ~/.bashrcс

if [[ $- != *i* ]]; then
  . ~/.profile
  return
fi

Zsh всегда читает, ~/.zshenvкогда начинается. Используйте с осторожностью, так как это читается каждым экземпляром zsh, даже если это подоболочка, где вы устанавливали другие переменные. Если zsh - это ваша оболочка входа в систему, и вы хотите использовать ее для установки переменных только для удаленных команд, используйте guard: установите некоторую переменную ~/.profile, например MY_ENVIRONMENT_HAS_BEEN_SET=yes, и проверьте эту защиту перед чтением ~/.profile.

if [[ -z $MY_ENVIRONMENT_HAS_BEEN_SET ]]; then emulate sh -c '~/.profile'; fi

Случай графических логинов

Многие дистрибутивы, дисплеи диспетчера и среды рабочего стола организованы для запуска ~/.profile, либо путем явного получения его из сценариев запуска, либо путем запуска оболочки входа.

К сожалению, не существует общего метода обработки комбинаций distro / DM / DE ~/.profile, которые не читаются.

Если вы используете традиционный сеанс, запущенный с помощью ~/.xsession, это место, где вы должны установить переменные среды; сделать это путем поиска ~/.profile(то есть . ~/.profile). Обратите внимание, что при некоторых настройках сценарии запуска среды рабочего стола будут исходить ~/.profileснова.

Жиль "ТАК - прекрати быть злым"
источник
что делает case $- in *i*)?
qodeninja
2
@qodeninja Выполняет следующие инструкции (до совпадения ;;или esac), если $-соответствует шаблону *i*, т.е. если $-содержит i, т.е. если оболочка является интерактивной.
Жиль "ТАК - перестань быть злым"
$-является строкой текущих установленных параметров оболочки. (как set -x) iозначает интерактивную оболочку.
Питер Кордес
Разве вы не можете просто найти общий файл, скажем ~/.config/env , даже без эмуляции?
Кевин Саттл
1
@ StéphaneChazelas Это пуристская точка зрения. Я соблюдаю свои .profileтребования относительно довольно старых оболочек Борна, но я понимаю, что некоторым людям просто все равно. Я ничего не имею против людей, предполагающих, что sh = bash для их собственных файлов, мне важно только, если они опубликуют #!/bin/shскрипт, использующий функции bash.
Жиль "ТАК - перестань быть злым"
4

Насколько я знаю, не существует никакого независимого от дистрибутива и оболочки стандарта, как устанавливать переменные окружения.

Наиболее распространенным и де-факто стандартом, кажется, является /etc/profileи ~/.profile. Вторым наиболее распространенным кажется /etc/environmentи ~/.pam_environment.

Мне кажется, что вся документация, которую я вам нашел, тоже уже найдена. Я перечислю их здесь в любом случае для других читателей.

  • Debian рекомендует /etc/profileи ~/.profile( ссылка ).
  • Ubuntu рекомендует /etc/environmentи ~/.pam_environment( ссылка ).
  • Arch Linux упоминает, среди прочего, /etc/profileи /etc/environment( ссылка ).

Бонус: текст, ставящий под сомнение использование и / или неправильное использование /etc/environmentв Debian ( ссылка , последнее обновление 2008).

lesmana
источник
Независимо от того, какой файл вы используете, вы все равно столкнетесь с несовместимым синтаксисом между различными оболочками.
Джозеф Р.
1
@JosephR. разве большинство оболочек не поддерживает обратную совместимость sh? Пока вы придерживаетесь POSIX, я бы подумал, что у вас все будет хорошо ...
evilsoup
1
AFAIK, вы не можете назначать переменные в cshдрузья POSIX (вам нужно что-то вроде setили setenv)
Джозеф Р.
0

Я добавил следующий скрипт ~ / bin / agnostic_setenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]="
   exit 0
endif

if ($#args == 2) then
   if ("$args[1]" =~ *csh*) then 
      echo "setenv $args[2]"
      exit 0
   else
      echo "export $args[1]=$args[2]"
      exit 0
   endif
endif

echo "setenv $args[2] $args[3]"

И в ~ / .perl-homedir я использую:

eval `${HOME}/bin/agnostic_setenv $shell PERL_HOMEDIR 0`

Примерный скрипт для agnostic_unsetenv:

#!/bin/csh -f
set args = ($*)
if ($#args == 1) then
   echo "export $args[1]"
   exit 0
endif

echo "unsetenv $args[2]"
exit 0
Коби
источник