Почему интерактивные оболочки в оболочках входа OSX по умолчанию?

43

В Linux и, насколько мне известно, во всех системах Unix эмуляторы терминала по умолчанию запускают интерактивные оболочки, не входящие в систему. Это означает, что для bash запущенная оболочка будет:

Когда запускается интерактивная оболочка, которая не является оболочкой входа в систему, bash читает и выполняет команды от /etc/bash.bashrcи ~/.bashrc, если эти файлы существуют. Это может быть запрещено с помощью --norc опции.

Опция --rcfile file заставит bash читать и выполнять команды из файла вместо /etc/bash.bashrcи ~/.bashrc.

А для логинов оболочек:

Когда bash вызывается как интерактивная оболочка входа в систему или как неинтерактивная оболочка с --loginпараметром, она сначала читает и выполняет команды из файла /etc/profile, если этот файл существует. После прочтения этого файла, он ищет ~/.bash_profile, ~/.bash_loginи ~/.profile, в таком порядке, и читает и выполняет команду из первого, который существует и читаемые.

Эта --noprofileопция может использоваться, когда оболочка запускается, чтобы запретить это поведение.

В OSX, однако, оболочка по умолчанию (то есть bash), запущенная в терминале по умолчанию (Terminal.app), фактически использует источники ~/.bash_profileи ~.profileт. Д. Другими словами, она действует как оболочка входа в систему.

Основной вопрос : почему интерактивная оболочка по умолчанию является оболочкой входа в OSX? Почему OSX решил сделать это? Это означает, что все инструкции / учебные пособия для вещей, основанных на оболочке, в которых упоминаются изменения ~/.bashrc, потерпят неудачу в OSX или наоборот ~/.profile. Тем не менее, хотя Apple может выдвинуть много обвинений, найм некомпетентных или идиотских разработчиков не является одним из них. Предположительно, у них были веские причины для этого, так почему?

Подвопросы: Terminal.app на самом деле запускает интерактивную оболочку входа или они изменили поведение bash? Это специфично для Terminal.app или не зависит от эмулятора терминала?

Тердон
источник
2
Terminal.app запускает оболочку входа. Я не знаю, почему Apple решила это сделать.
Жиль "ТАК - перестань быть злым"
Кстати, для macOS Catalina оболочкой по умолчанию является zsh .
Василий Бурк

Ответы:

33

Так , как это предполагается работа заключается в том, в тот момент , когда вы получите приглашение оболочки, как .profileи .bashrcзапускались. Конкретные детали того, как вы доберетесь до этой точки, имеют второстепенное значение, но если какой-либо из файлов вообще не запустится, у вас будет оболочка с неполными настройками.

Причина, по которой эмуляторы терминала в Linux (и других системах на основе X) не должны запускаться .profileсами по себе, заключается в том, что он обычно запускается уже при входе в X. Предполагается, что настройки в нем .profileмогут быть такими наследуется подпроцессами, поэтому до тех пор, пока он выполняется один раз, когда вы входите в систему (например, через .Xsession), никаким другим подоболочкам не требуется его повторный запуск.

Поскольку страница вики Debian связана Алан Шутко объясняет:

«Почему же тогда .bashrcотдельный файл .bash_profile? Это делается по большей части по историческим причинам, когда машины работают очень медленно по сравнению с современными рабочими станциями. Обработка команд .profileили .bash_profileможет занять довольно много времени, особенно на машине, где много работы Это должно было быть сделано с помощью внешних команд (pre-bash). Таким образом, вводятся сложные начальные команды настройки, которые создают переменные среды, которые могут передаваться дочерним процессам .bash_profile. Переходные параметры и псевдонимы, которые не наследуются, помещаются в .bashrcтак что они могут быть повторно прочитано каждой субоболочка «.

Все те же правила действуют и в OSX, за исключением одного: графический интерфейс OSX не запускается .profileпри входе в систему, очевидно, потому что у него есть свой собственный метод загрузки глобальных настроек. Но это означает , что эмулятор терминала на OSX делает необходимость запуска .profile(рассказав её оболочки пуски , что это Войти оболочки), в противном случае вы бы в конечном итоге с потенциально хромого оболочкой.


Теперь, некоторая глупая особенность bash, которую не разделяют большинство других оболочек, заключается в том, что она не запускается автоматически, .bashrcесли она запускается как оболочка входа в систему. Стандартный обходной путь для этого должен включать в себя что-то вроде следующих команд .bash_profile:

[[ -e ~/.profile ]] && source ~/.profile    # load generic profile settings
[[ -e ~/.bashrc  ]] && source ~/.bashrc     # load aliases etc.

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

Если OSX по умолчанию .bash_profileили .profile не делает этого, то это, возможно, ошибка. В любом случае, правильное решение - просто добавить эти строки .bash_profile.


Редактирование: Как отмечается в примечании , оболочкой по умолчанию в OSX была tcsh, поведение которой намного более разумно в этом отношении: при запуске в качестве интерактивной оболочки входа в систему tcsh автоматически считывает .profile и .tcshrc / .cshrc, и, таким образом, не требует никаких обходных путей, таких как .bash_profileтрюк показано выше.

Исходя из этого, я на 99% уверен, что отказ OSX предоставить соответствующее значение по умолчанию .bash_profileобъясняется тем, что, когда они переключались с tcsh на bash, люди из Apple просто не заметили эту маленькую брешь в поведении запуска bash. С tcsh такие трюки не нужны - запуск tcsh в качестве оболочки для входа из эмулятора терминала OSX Just Plain Works и делает все правильно без таких клугов.

Илмари Каронен
источник
1
Спасибо, я все это знал. У меня вопрос: почему OSX решил настроить таким образом, чтобы сделать его .bashrcнеуместным? Почему они решили сделать все оболочки входными? Насколько я могу судить, только ваше последнее предложение относится к этому и только сказать, что это ошибка.
Terdon
1
Нет, проблема в том, что они запускают оболочки входа в свои эмуляторы терминала. Точечные файлы - это поведение bash по умолчанию, при запуске оболочки входа в систему будут считываться профили и т. Д., А не bashrc и т. Д. Вопрос в том, почему оболочки входа в систему запускаются вместо не-входа в систему.
Terdon
2
Да, и я, и Алан объяснили, что это потому, что, в отличие от Linux, OSX не запускается, .profileкогда пользователь входит в GUI, поэтому он должен выполнить его позже, чтобы получить переменные среды, такие как $PATH, которые обычно установлены .profile, настроены правильно , Тот факт, что в качестве побочного эффекта это .bashrcне приводит к источнику, является ошибкой; вы можете спорить о том, является ли это ошибкой в ​​bash или в OSX, но это не меняет того факта, что правильное поведение будет гарантировать, что загружаются как переменные среды, так .profileи параметр конфигурации bash .bashrc.
Илмари Каронен
1
Иметь .bashrcисходники .profileбыло бы плохой идеей, так как это заставляло бы перезапускать каждую подоболочку .profile. Если ничего другого, это может привести к распространенным .profileидиомам, например, export PATH = "$HOME/bin:$PATH"к продолжению добавления избыточных записей $PATH. Наличие .profileисходного кода .bashrcимеет больше смысла, но только после проверки того, что оболочка, в которой он работает, фактически является bash. Иметь .bash_profileисточник, .profile и .bashrc , как я уже говорил выше, ИМО - самый разумный вариант.
Ильмари Каронен,
2
И я говорю ответ на вопрос «почему они используют оболочку входа?» «потому что они нуждаются в нагрузку .profile», в то время как ответ на вопрос «почему они не источник .bashrcиз .profile, тогда?» это "потому что это ошибка!" Серьезно, это не может быть намеренным решением; это просто то, что они упустили из виду, предположительно потому, что в экосистеме Mac оболочки - это граждане второго сорта, с которыми большинству пользователей не приходится иметь дело. (Ps. См. Также ответ Струге для исторического объяснения; это почти наверняка регресс от перехода от tcsh к bash.)
Ильмари Каронен,
14

Основная причина того, что приложения X-терминала по умолчанию запускают не входящие в систему оболочки, состоит в том, что в начале вашего .Xsession запустил .profile для настройки ваших начальных элементов входа в систему. Затем, поскольку все это уже было настроено, терминальным приложениям не нужно было его запускать, они могли запускать .bashrc. Обсуждение того, почему это имеет значение, можно найти на https://wiki.debian.org/DotFiles :

Давайте возьмем xdm в качестве примера. Однажды Пьер возвращается из отпуска и обнаруживает, что его системный администратор установил xdm в систему Debian. Он просто входит в систему, и xdm читает его файл .xsession и запускает fluxbox. Кажется, все в порядке, пока он не получит сообщение об ошибке в неправильной локали! Поскольку он переопределяет переменную LANG в своем .bash_profile, а xdm никогда не читает .bash_profile, его переменная LANG теперь установлена ​​в en_US вместо fr_CA.

Теперь наивное решение этой проблемы состоит в том, что вместо запуска «xterm» он может настроить свой оконный менеджер на запуск «xterm -ls». Этот флаг сообщает xterm, что вместо запуска обычной оболочки следует запустить оболочку входа в систему. При такой настройке xterm порождает / bin / bash, но в вектор аргумента помещает «- / bin / bash» (или, может быть, «-bash»), поэтому bash действует как оболочка входа в систему. Это означает, что каждый раз, когда он открывает новый xterm, он будет читать / etc / profile и .bash_profile (встроенное поведение bash), а затем .bashrc (потому что .bash_profile говорит об этом). На первый взгляд может показаться, что это работает нормально - его точечные файлы не тяжелые, поэтому он даже не замечает задержки - но есть более тонкая проблема. Он также запускает веб-браузер прямо из меню Fluxbox, и веб-браузер наследует переменную LANG от fluxbox, который теперь настроен на неправильную локаль. Таким образом, хотя его xterms могут быть в порядке, и все, что запускается из его xterms, может быть в порядке, его веб-браузер по-прежнему предоставляет ему страницы в неправильной локали.

В OS X пользовательские среды не запускаются кучей сценариев оболочки, а launchd не создает .profile в любое время. (Это своего рода позор, так как это означает, что устанавливать переменные среды намного раздражает, но такова жизнь.) Так как это не так, когда он запускает .profile? Только если ты ssh'd в? Это кажется бессмысленным, поскольку многие блоки никогда не будут мишенями для ssh. Можно также заставить терминалы запускать оболочки входа в систему по умолчанию, так что .profile будет запущен когда-нибудь.

Тогда как насчет .bashrc? Это бесполезно? Нет. У него все еще есть цель, которую он имел во времена VT100. Он используется для любого времени, когда вы открываете оболочку, кроме открытия окна терминала. Так что если вы используете оболочку из Emacs или vi, или если вы используете пользователя su.

Алан Шутко
источник
1
На странице Debian, которую вы цитируете, объясняется, почему .profileисточники Debian .bashrc, а не то, почему OSX решила сделать все оболочки для входа в систему по умолчанию. На самом деле, вы отвечаете на другой мой вопрос , и спасибо! Однако, ваш ответ не объясняет выбор OSX, и цитата Debian здесь, насколько я могу судить, совершенно неактуальна (пожалуйста, дайте мне знать, если я просто упускаю суть). OSX способ сделать .bashrcбесполезным и т. Д. И не делает .profileбольше полезным.
Тердон
4

Я не знаю, почему они это сделали. Однако вот мое предположение.

Для начала стоит отметить, что в системе GNU / Linux вы, конечно, можете переключиться на vt1, vt2 и т. Д. Там вы получите оболочку входа. В системе OS X нет аналога. Единственный способ получить доступ к основам UNIX - через эмулятор терминала или однопользовательский режим (отказ от ответственности: на самом деле я никогда не использовал однопользовательский режим; это IIRC, управляемый из командной строки, но я могу ошибаться). Следовательно, в OS X, что бы ни было по умолчанию в эмуляторе, это значение по умолчанию для всей системы.

Теперь, почему бы вам сделать оболочку входа по умолчанию? Есть пара (читай: не так много) причин, по которым я могу придумать это.

  • Это обеспечивает согласованное взаимодействие с пользователем, если вы используете SSH. (Особенно важно для серверной версии OS X - по-видимому, если вы используете сервер OS X, вы новичок.)
  • Оболочка по умолчанию OS X была раньше tcsh. Это довольно дикое предположение, которое вы можете получить, но может случиться так, что tcshобычно что-то делает, когда запускается как оболочка входа в систему, и исторический шаблон застрял. (Я сомневаюсь в этом, хотя - возможно, один из старших завсегдатаев мог бы сказать нам.)
  • «Мы - Apple. Мы являемся поставщиками крупнейшего дистрибутива UNIX на планете. Неважно, насколько тривиальны наши причины; если мы примем решение, ваш инструмент должен с ним справиться».

Честно говоря, я пользуюсь дарвином ~ 6 лет и не могу ответить на этот вопрос должным образом. Для меня это тоже не имеет смысла.

Чтобы ответить на ваш вопрос, bashне пропатчен или что-нибудь (по крайней мере для этого). Эмулятор терминала по умолчанию запускает оболочки входа по умолчанию, и, вероятно, iTerm копирует это.

strugee
источник
1
+1 за упоминание tcsh, поскольку его поведение в этом отношении намного более разумно, чем bash: при запуске в качестве интерактивной оболочки входа в систему tcsh использует оба источника .profileи .tcshrc/ или .cshrcне требует никаких клугов, подобных тому, который я дал в своем ответе. Учитывая это, я подозреваю, что такое поведение является нефиксированной регрессией, вызванной переключением с tcsh на bash.
Илмари Каронен
@IlmariKaronen Вы имеете в виду (здесь и там ), что источники tcsh .loginи .tcshrc/ .cshrc? Это не имело бы смысла для tcsh к источнику .profile; обычно он содержит команды с shсинтаксисом, tcshкоторые не будут приниматься. У меня нет macOS, но я создал /bin/tcshсвою оболочку для входа в Ubuntu 16.04. .profileне получены. tcsh (1) не упоминает этот файл, также как и этот tcsh (1) .
Элия ​​Каган
3

Это обновление до текущего состояния: ответы устарели, поскольку были выпущены новые версии MacOSX и изменилось поведение при входе.

Этот вопрос был задан и получен ответ в 2014 году. Я изучал эту тему, пытаясь создать общий набор .bashrc & .bash_profile для использования в разных дистрибутивах Linux и BSD (как они их называют, если они не дистрибутивы).

Недавно я купил подержанный Mac Mini с установленной Sierra, поэтому у меня теперь есть системы с 10.6, 10.10, 10.11 и 10.12. Несмотря на то, что я разобрал старые (оставив ключи к их предыдущему состоянию), установка Sierra 10.12 не затронута.

Результаты: в 10.12 Sierra по умолчанию НЕТ .bashrc, .bash_profile или .profile. В / etc есть bashrc, bashrc_Apple_Terminal и профиль. Содержимое / etc / profile:

# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

Содержимое / etc / bashrc:

# System-wide .bashrc file for interactive bash(1) shells.
if [ -z "$PS1" ]; then
   return
fi

PS1='\h:\W \u\$ '
# Make bash check its window size after a process completes
shopt -s checkwinsize

[ -r "/etc/bashrc_$TERM_PROGRAM" ] && . "/etc/bashrc_$TERM_PROGRAM"

Сценарий / etc / bashrc_Apple_Terminal устанавливает переменную PROMPT_COMMAND и устанавливает механизм сохранения состояния сеанса для каждого терминала; если приложение терминала закрыто, состояние предыдущего сеанса восстанавливается при повторном запуске приложения. В противном случае почти ничего (минимальный $ PS1) не устанавливается в / etc / bashrc, оставляя любые другие настройки (реальные $ PS1, псевдонимы, функции) для настройки в ~ / .bashrc и $ PATH в .bash_profile (или в .profile) Источник: .bash_profile).

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

Если вы запустите сеанс терминала X11 (теперь XQuartz) XTerm, вы увидите сеанс без входа в систему, такой же, как в системе Linux; .bash_profile (или .profile) пропускается, и вы просто получаете .bashrc.

И вот мой ответ:

Хотя приложение Terminal и утверждает, что оно является xterm (TERM = xterm-256color), оно не устанавливает переменную $ DISPLAY, если не установлен X11. Мы наблюдаем симуляцию X-среды, но не совсем реальной. Если вы подключитесь по SSH к другой системе с ключом -X (включите пересылку X11), произойдет сбой, поскольку переменная $ DISPLAY отсутствует. Если вы установили X11, а затем SSH в другую систему, пересылка X11 будет успешной.

Итог (и короткий ответ): приложение Terminal не является истинным терминалом X11 (не устанавливает $ DISPLAY); он ведет себя намного больше как логин SSH, чем сеанс XTerm, в том смысле, что он должен быть сеансом входа в систему для установки значений из / etc / profile и ~ / .bash_profile или ~ / .profile

donls
источник
0

Ответы выше объяснили причину , почему интерактивные оболочки входа снаряды на MacOs по умолчанию: настройки /etc/profile, ~/.profileнаследуется нерегистрированной оболочкой на системах X основы, а не на MacOS . Здесь я хочу напомнить вам, что вы всегда должны использовать оболочку входа в MacOS из-за существования path_helper:

 cat /etc/profile # or cat /etc/zprofile
# System-wide .profile for sh(1)

if [ -x /usr/libexec/path_helper ]; then
    eval `/usr/libexec/path_helper -s`
fi

if [ "${BASH-no}" != "no" ]; then
    [ -r /etc/bashrc ] && . /etc/bashrc
fi

path_helperУтилита считывает содержимое файлов в каталогах , /etc/paths.dи /etc/manpaths.d и добавляет их содержимое в PATHи MANPATHпеременных окружения соответственно. ( MANPATHПеременная среды не будет изменена, если она уже не установлена ​​в среде.)

Если вы используете оболочку без входа в систему, некоторые пути не будут импортированы.

Я думаю, что для разработчика всегда хорошая идея поместить файл, /etc/paths.dчтобы импортировать их значения пути, но не ставить символическую ссылку на вызываемые двоичные файлы в такие места, как /usr/binили /bin. (По умолчанию PATHэто /usr/bin:/bin:/usr/sbin:/sbin. Не каждый использует Homebrew или MacPorts добавления пользовательских значений в PATH. Так что не всегда безопасное место , чтобы поставить симлинку ИХ команд.)

Вот пример файлов в /etc/paths.d. По сути, вы ставите одно значение в каждой строке.

 cat /etc/paths.d/Wireshark
/Applications/Wireshark.app/Contents/MacOS

Ссылка:

Simba
источник