Назначение [-n "$ PS1"] в bashrc

Какую цель делает [ -n "$PS1" ] в [ -n "$PS1" ] && source ~/.bash_profile; служить? Эта строка включена в .bashrc для dotfiles repo .

10 голосов | спросил shotes 15 AM00000070000003831 2018, 07:40:38

4 ответа


20

Это проверка, является ли оболочка интерактивной или нет. В этом случае только поиск файла ~/.bash_profile, если оболочка является интерактивной.

См. «Является ли эта оболочка взаимодействующей?» в руководстве bash, которое ссылается на эту конкретную идиому. (Он также рекомендует проверить, является ли оболочка интерактивной, проверяя, содержит ли специальная переменная $- i, что является лучшим подходом к этой проблеме.)

ответил Filipe Brandenburger 15 AM00000070000005931 2018, 07:57:59
18

Что это делает

Это широко распространенный способ проверить, является ли оболочка интерактивной. Помните, что он работает только в bash, он не работает с другими оболочками. Итак, это нормально (если глупо) для .bashrc, но это не сработает в .profile (который считывается sh, а bash - только одна из возможных реализаций sh, а не самая распространенная).

Почему это работает (только в bash!)

Интерактивная оболочка устанавливает shell variable PS1 в строку приглашения по умолчанию. Поэтому, если оболочка интерактивна, устанавливается PS1 (если пользовательский .bashrc удалил его, что еще не могло произойти в верхней части .bashrc, и вы могли бы подумать, что во всяком случае, это глупо).

Обратное верно в bash: неинтерактивные экземпляры bash unset PS1, когда они начинаются. Обратите внимание, что это поведение специфично для bash и, возможно, является ошибкой (почему bash -c '… do stuff with $var…' не работает, когда var является PS1?). Но все версии bash до 4.4 включительно (последняя версия, когда я пишу) делают это.

Многие системы экспортируют PS1 в среду. Это плохая идея, потому что многие разные оболочки используют PS1, но с другим синтаксисом (например, подсказки подсказки bash полностью отличаются от подсказки zsh's prompt ). Но достаточно широко распространено, что на практике, если установить PS1, не является надежным индикатором того, что оболочка является интерактивной. Оболочка могла бы наследовать ---- +: = 13 =: + ---- из среды.

Почему это (неправильно) используется здесь

PS1 - это файл, который bash читает при запуске, когда он является интерактивным. Менее известный факт заключается в том, что bash также читает .bashrc - это оболочка входа, а эвристика bash заключает, что это удаленный сеанс (проверки bash если его родительский код .bashrc или rshd) , В этом втором случае маловероятно, что в среде будет установлен sshd, потому что ни один файл dot еще не запущен.

Однако способ использования этой информации контрпродуктивен.

  • Если оболочка является интерактивной оболочкой, то в этой оболочке выполняется PS1. Но .bash_profile - это сценарий времени входа в систему. Он может запускать некоторые программы, которые предназначены для запуска только один раз за сеанс. Он может переопределить некоторые переменные среды, которые пользователь преднамеренно установил для другого значения перед запуском этой оболочки. Запуск .bash_profile в оболочке, не входящей в систему, является разрушительным.
  • Если оболочка не является интерактивной удаленной оболочкой входа, она не загрузит .bash_profile. Но это тот случай, когда загрузка .bash_profile может быть полезна, поскольку неинтерактивная оболочка входа не загружает автоматически .bash_profile и /etc/profile.

Я думаю, что люди делают это для пользователей, которые входят в систему через графический интерфейс (очень распространенный случай), и которые задают свои параметры переменной среды в ~/.profile, а не .bash_profile. Большинство механизмов входа в GUI вызывают .profile, но не .profile (чтение .bash_profile потребует запуск bash как часть запуска сеанса, а не sh). В этой конфигурации, когда пользователь открывает терминал, они получат свои переменные среды.Тем не менее, пользователь не получит свои переменные окружения в приложениях с графическим интерфейсом, что является очень распространенным источником путаницы. Решением здесь является использование .bash_profile вместо .profile для установки переменных среды. Добавление моста между .bash_profile и .bashrc создает больше проблем, чем решает.

Что делать вместо

Существует простой, переносимый способ проверки, является ли текущая оболочка интерактивной: проверьте, включена ли опция .bash_profile.

-i

Это полезно в case $- in *i*) echo "This shell is interactive";; *) echo "This shell is not interactive";; esac до читать .bashrc, только если оболочка не является интерактивной - то есть противоположность тому, что делает код! Прочитайте .profile, если bash является (неинтерактивной) оболочкой входа и не читает ее, если это интерактивная оболочка.

.profile
ответил Gilles 15 AM00000090000000731 2018, 09:31:07
1

Похоже, что эта странная концепция является результатом того, что bash не запускался как клон оболочки POSIX, а как ---- +: = 1 =: + ----.

В результате интерактивное поведение POSIX (Bourne Shell вызывается для интерактивных оболочек) добавлено позже в $ENV и не широко известен.

Существует одна оболочка, которая предоставляет подобное поведение. Это bash и csh предоставляет, что csh имеет определенные значения:

$prompt

Но это не относится к оболочке Bourne или к оболочкам POSIX.

Для оболочки POSIX единственным предоставленным методом является включение в файл кода для интерактивных оболочек:

$prompt not set          non-interactive shell, test $?prompt.
$prompt set but == ""    .cshrc called by the which(1) command.
$prompt set and != ""    normal interactive shell.

, который имеет имя оболочки. Это, например,

$ENV

Другие люди упомянули флаг оболочки $HOME/.kshrc for the korn shell $HOME/.bashrc for bash $HOME/.mkshrc for mksh $HOME/.shrc for the POSIX Bourne Shell , но это невозможно для надежного программирования. POSIX не требует, чтобы -i, а не set -i содержит $- для интерактивных оболочек. POSIX просто требует, чтобы i принудительно вводил оболочку в интерактивный режим.

Поскольку переменная sh -i может быть импортирована из среды, она может иметь значение даже в неинтерактивном режиме. Тот факт, что $PS1 bash s unset в любой неинтерактивной оболочке не предоставляется стандартом и не выполняется какой-либо другой оболочкой.

Таким образом, чистое программирование (даже с помощью PS1) состоит в том, чтобы поместить команды для интерактивных оболочек в bash

ответил schily 15 PM000000120000001031 2018, 12:41:10
0

Я собираюсь сначала поговорить о том, что Debian, и большую часть времени Ubuntu устанавливает для bash. И последнее касается других систем.

В настройке файлов запуска оболочки есть много мнений.
У меня также есть свое мнение, но я попытаюсь показать существующие примеры правильных настроек.
Я буду использовать debuan, так как довольно легко найти примеры его файлов.
И debian сильно используется, поэтому настройки были хорошо протестированы,

Какова цель проверки того, что установлен PS1?

Только чтобы узнать, является ли оболочка интерактивной.

по умолчанию /etc/profile в debian и ubuntu (из /usr /share /base-files /profile):

if [ "${PS1-}" ]; then
    if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then

Чтение if: if interactive (по умолчанию установлено PS1), и это оболочка bash (но не действующая как по умолчанию sh) затем измените PS1 на конкретный новый (не по умолчанию).

по умолчанию /etc/bash.bashrc в debian также содержит:

# If not running interactively, don't do anything
[ -z "$PS1" ] && return

Что довольно ясно в том, что он делает: если интерактивный не источник (остальное).

Однако в /etc/skel/.bashrc является пример правильного способа проверки интерактивной оболочки (используя $-):

# If not running interactively, don't do anything
case $- in
    *i*) ;;
      *) return;;
esac

Это должно четко показать, почему PS1 и одна альтернатива.

Правильный порядок

Следует избегать установки, о которой вы сообщаете.
Порядок (от системных настроек до более конкретных пользовательских настроек (для bash)): /etc/profile, /etc/bash.bashrc, ~/.profile и, наконец, ~/.bashrc. Это наиболее распространенные эффекты (и для большего количества оболочек) в /etc/profile (который принадлежит root), за которым следует /etc/bash.bashrc (который также принадлежит root), но влияет только на bash. Затем введите персональные настройки в $HOME, первый - ~/.profile для большинства оболочек и ~/.bashrc (почти эквивалентно ~/.bash_profile), только для bash.

Поэтому неправильно использовать источник ~/.bashrc в ~/.profile, он преобразует определенный пользовательский параметр для bash в более общий, который влияет на большее количество оболочек . Если сделано таким образом :

# ~/.profile: executed by the command interpreter for login shells
# if running bash
if [ -n "$BASH_VERSION" ]; then
    # include .bashrc if it exists
    if [ -f "$HOME/.bashrc" ]; then
    . "$HOME/.bashrc"
    fi
fi

Он проверяет, что bash запущен и загружает .bashrc, если это так.

Это решение для верхнего уровня, поступающее от Debian. Обоснование объяснено здесь .

На самом деле, обратное, поиск ~/.profile в ~/.bash_profile (или ~/.bashrc) только повторно применяет общие правила, которые должны были быть загружены уже в конкретный прецедент, и поэтому «не так уж плохо» (я не говорю «хорошо»). И я не говорю «хорошо», потому что это может вызвать поиск файлов в цикле. Например, когда подкаталог загружает родительский элемент, то есть цикл каталога.

И в этом перекрестном поиске, что проверка для интерактивной оболочки имеет смысл. Только когда оболочка является интерактивной, загружается ~/.bashrc, но она, в свою очередь, может быть загружена ~/.profile (или наоборот), и в этом случае можно использовать проверку для интерактивной оболочки.

ответил Isaac 18 AM00000060000002931 2018, 06:31:29

Похожие вопросы

Популярные теги

security × 330linux × 316macos × 2827 × 268performance × 244command-line × 241sql-server × 235joomla-3.x × 222java × 189c++ × 186windows × 180cisco × 168bash × 158c# × 142gmail × 139arduino-uno × 139javascript × 134ssh × 133seo × 132mysql × 132