Куда мне экспортировать переменную среды, чтобы все комбинации bash / dash, интерактивные / неинтерактивные, вход в систему / не вход в систему, подхватили ее?

11

Вот мотивация для вопроса:

Я использую Ubuntu 12.04 LTS 2 с рабочим столом Unity. В моем файле .bashrc я добавляю несколько каталогов к моей переменной PATH и определяю несколько переменных среды, таких как JAVA_HOME. Когда я запускаю приложения из терминала (запускаю bash, мою оболочку по умолчанию), это прекрасно работает, но для некоторых из ярлыков, использующих панель запуска Unity, они запускают приложения, которые, похоже, определены для использования #! / Bin / sh, который имеет псевдоним / bin / dash, и они не получают содержимое ни ~ / .bashrc, ни ~ / .profile.

Я полагаю, что я мог бы изменить все эти сочетания клавиш, чтобы использовать / bin / bash вместо / bin / sh, чтобы заставить его воспринимать изменения .bashrc, но это выглядит очень странно.

Учитывая, что Ubuntu 12.04 (по умолчанию) использует псевдонимы / bin / sh для / bin / dash и что моя оболочка по умолчанию - / bin / bash, есть ли единственное место, где я могу изменить PATH и определить переменные окружения, если они мне нужны? присутствовать при всех этих обстоятельствах:

  1. Всякий раз, когда я создаю оболочку bash без входа в систему (используя терминал в единстве)
  2. Всякий раз, когда я создаю оболочку bash для входа (например, удаленный вход через ssh)
  3. Всякий раз, когда я использую модуль запуска приложений Unity (учитывая, что модуль запуска использует / bin / sh).
  4. Всякий раз, когда выполняется задание cron (учитывая, что SHELL = / bin / sh в / etc / crontab).

Если я правильно понимаю, я предполагаю, что:

  • (1) / (2) и (3) / (4) различаются, потому что (1) / (2) - bash, а (3) / (4) - dash.
  • (1) и (2) различаются, потому что файлы, которые bash выбирает для загрузки, отличаются в зависимости от того, является ли это оболочкой входа в систему.
  • (3) и (4) различаются, потому что (3) придет в какой-то момент после того, как я войду в систему (и, следовательно, ~ / .profile будет получен одним из его родительских процессов, в то время как (4) придет в некоторый Точка, когда я не вошел в систему, и, следовательно, ~ / .profile не будет прочитан.

(Я не удивлюсь, если будут иметь значение и другие факторы, например, является ли оболочка интерактивной, так что, возможно, есть и другие комбинации, которые я даже не ожидал ... Я рад, что мой вопрос "улучшен" " в этом случае.)

Я ожидаю, что в какой-то момент кто-то должен был создать какое-то руководство, которое расскажет вам, как / где модифицировать переменные среды независимым от оболочки способом (или, по крайней мере, совместимым с dash / bash способом) ... Я просто могу ' Кажется, что не найти правильные условия поиска, чтобы найти такое руководство.

Решения или указатели на решения приветствуются!

Обновлено:

  • Пояснение: это пользователь Ubuntu по умолчанию, созданный в процессе установки 12.04, так что ничего особенного. Это действительно есть ~ / .profile (что явно источники ~ / .bashrc), и только ~ / .bash * файлы представляют не .bashrc, .bash_history и .bash_logout ... так нет нет .bash_profile.
  • Акцент на области применения: меня не волнуют никакие оболочки, кроме интерактивной оболочки по умолчанию (bash) и любого сценария, который использует / bin / sh (с псевдонимом dash), поэтому нет необходимости усложнять это чем-то дополнительным для Tcsh / КШ / ЗШ / и т.д.. служба поддержки.
Mickalot
источник
2
Поместите его в один файл, а затем пусть его получат другие файлы rc.
konsolebox
В соответствии со страницей справочной системы, которую я имею, здесь должно быть чтение $ HOME / .profile для оболочек входа.
Этан Рейснер
@konsolebox Какие rc файлы? AFAICT, у dash нет rc-файла. И, как я уже сказал, dash, похоже, не собирает содержимое ~ / .profile.
@EtanReisner Да, и в этом суть вопроса. Когда dash не работает как оболочка для входа (и, следовательно, ~ / .profile не поставляется), что тогда?
@Mickalot Вы работаете в интерактивном режиме? Если нет, попробуйте добавить опцию -l.
konsolebox

Ответы:

9

Вызов Shell - сложная вещь. На страницах руководства bash и dash есть INVOCATIONразделы об этом.

В итоге они говорят (есть более подробная информация на странице руководства, вы должны прочитать это):

When bash is                   | it reads
-------------------------------|----------
login shell                    | /etc/profile and then the first of ~/.bash_profile, ~/.bash_login or ~/.profile that exists.
                               |
interactive non-login shell    | /etc/bash.bashrc then ~/.bashrc
                               |
non-interactive shell          | The contents of $BASH_ENV (if it exists)
                               |
interactive (as "sh")          | The contents of $ENV (if it exists)

-

When dash is                   | it reads
-------------------------------|---------
login shell                    | /etc/profile then .profile
                               |
interactive shell              | The contents of ENV (it it exists, can be set in .profile as well as in initial environment)

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

Этан Рейснер
источник
К сожалению, суть этой проблемы заключается в том, чего не хватает на вашем столе. Когда рабочий стол Unity вызывает любой сценарий, начинающийся с #! / Bin / sh, он запускает (что я предполагаю, что) неинтерактивную, неинтерактивную dash-оболочку. Таким образом, вопрос: как сделать, чтобы одни и те же переменные окружения доступны там , которые присутствуют везде в матрице?
Правильно. Я думаю, что именно поэтому Bash добавил BASH_ENV для этого слота. Учитывая, что в этом слоте, по-видимому, нет ничего, что работает в этом слоте, я не уверен, что вы сможете решить эту проблему, не затрагивая изменения в среде приложения, которое запускает дефис (такой, что дефис наследует его). Это потребует установки переменных среды в вашей среде X, где вступает в действие комментарий .xsession (rc) от @Mickalot. Это все еще оставляет, как он указал, пункт четвертый пропущенным (но я полагаю, что это на самом деле несколько намеренно).
Этан Рейснер
Так как я на Ubuntu 12.04 LTS, cron на самом деле является pixie-cron, поэтому я могу определить переменные env в моем файле crontab ... Я предполагаю, что SHELL = / bin / bash и BASH_ENV = ~ / .bashrc должны это делать?
3

Итак, есть несколько способов подойти к этому. Многие люди будут либо:

а. Имейте один файл, который имеет общие черты для всех ваших оболочек в стиле sh, скажем, .shcommonи в каждом из .profile .bashrc .kshrcet cetra, просто поставьте его с. .shcommon

б. Поместите все в .profileи источник этого из других файлов.

Вещи, которые необходимы для определенных оболочек или для интерактивных и неинтерактивных оболочек, могут быть переданы в соответствующий файл перед поиском .shcommon

Лично мне не нравится управлять несколькими файлами. Итак, я использую следующий подход:

Во-первых, все, что мне нужно, .profile связано с тем, что у меня есть некоторые специфичные для bash и ksh вещи, я определяю текущее имя оболочки, используя следующее:

# get name of current shell
# strip leading - from login shell
export SHELLNAME="${0#-}"

и затем иметь команды для определенных оболочек в чем-то вроде следующего (некоторые предпочли бы оператор case).

if [ "$SHELLNAME" = 'bash' ]
then
    shopt -s checkwinsize

elif [ "$SHELLNAME" = 'ksh' ]
then
    stty erase ^?
fi

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

# check for interactive flag i in shell options $-
# in bash and ksh you could use the following, but breaks in dash
# if [[ $- == *i* ]]
if [ "$(echo $- | grep i)" != "" ]
then
  fortune
fi

Вещи, которые распространены во всех оболочках стиля sh, например, PATHмогут просто идти наверх.

Затем я использую символические ссылки для загрузки этого файла во все оболочки sh-style:

ln -s .profile .bashrc
ln -s .profile .kshrc

Пара дополнительных замечаний, если у вас есть .bash_profile, то bash загрузит это вместо, .profileно dash и ksh все равно загрузят. .profile Это может быть частью вашей проблемы.

Кроме того, вы можете рассмотреть возможность использования #!/bin/bashв своих сценариях вместо тех #!/bin/dashслучаев, когда вам действительно нужны POSIX-совместимые сценарии. В bash есть много дополнительных функций, которые очень хороши, и dash или bash вызываются, так как sh отключит многие из этих функций.

Кроме того, справочная страница bash хорошо объясняет, когда загружается .profileпротив .bashrc. Аналогичные правила применяются к ksh. dash загружает .profileпри входе в систему и позволяет загружать файл при запуске интерактивных оболочек, который указывается с помощью ENVпеременной среды в .profile(проверьте также страницу руководства dash и найдите .profile).


источник
Не могли бы вы просто проверить $ 0 для имени оболочки? Есть ли оболочки / случаи, когда это не работает?
Этан Рейснер
Точно так же проверки i в $ не достаточно для проверки интерактивной оболочки? (Он будет срабатывать на интерактивных оболочках без tty, который я предоставляю, но это может или не может быть нежелательным побочным эффектом.)
Etan Reisner
@Etan: Хм, я знаю, что я сначала попробовал $0и столкнулся с проблемами ... Я не могу вспомнить точно, что они были, хотя. Вход непосредственно в консоль показывает, $0что -bashвместо, bashно это можно исправить.
@Etan: Да, проверка для меня $-также будет работать. Я бы подумал, когда у вас будет интерактивная оболочка без tty? По какой-то причине ваше решение лучше воспринимается, я могу это изменить.
Значение -in -bashозначает «оболочка входа в систему», но да, вам необходимо учитывать это в местах, где вы проверяете значение или хотите показать его кому-либо.
Этан Рейснер
0

Так как случаи (1) и (2) решаются путем поиска переменных окружения в .bashrc и .profile, реальный вопрос заключается в том, «как называется файл, в котором я получаю эти же переменные для (3) и (4).

Похоже, что есть ответ на часть (3) вопроса (как я могу получить переменную среды для импорта на рабочий стол Unity) в askubuntu . Здесь предлагается создать файл ~ / .xsessionrc, который будет получен из / etc / X11 / Xsession. (Я попробовал это, и это похоже на работу ... ууу!)

Я все еще озадачен тем, что делать для (4). Конечно, если я создаю задание cron (или демон), я могу заменить '/ bin / foo' на что-то вроде 'bash -i -c / bin / foo', чтобы заставить его использовать bash для загрузки правильных переменных среды, но это также означает, что мне придется возиться с любыми сторонними инструментами, которые могут устанавливать задачи демона или задачи cron от моего имени. ЮК.

Mickalot
источник