Ответы:
Это проверяет, является ли оболочка интерактивной или нет. В этом случае, только поиск ~/.bash_profile
файла, если оболочка является интерактивной.
Смотрите "Является ли эта оболочка интерактивной?" в руководстве по bash, которое цитирует эту специфическую идиому. (Также рекомендуется проверить, является ли оболочка интерактивной, проверив, $-
содержит ли специальная переменная i
символ, что является лучшим подходом к этой проблеме.)
bash
сбрасывает PS1, когда неинтерактивный (опечатка в вашем предыдущем комментарии) является ошибкой IMO, PS1 не является специфичной для bash переменной, он не имеет смысла ее сбрасывать. Это единственная оболочка, которая делает это (хотя yash
также устанавливает PS1
значение по умолчанию, даже когда не является интерактивным).
[[ $- = *i* ]] && source ~/.bash_profile
).
[ -n "${PS1}" ]
, но я все же обновил свой ответ, чтобы подчеркнуть, что руководство по bash также предлагает / рекомендует проверять, $-
является ли оболочка интерактивной, надеюсь, вы найдете, что это улучшает ответ. Ура!
Это широко распространенный способ проверки, является ли оболочка интерактивной. Помните, что он работает только в bash, он не работает с другими оболочками. Так что это нормально (если глупо) для .bashrc
, но это не сработает .profile
(это читается sh, а bash - только одна из возможных реализаций sh, и не самая распространенная).
Интерактивная оболочка устанавливает переменную оболочкиPS1
в строку приглашения по умолчанию. Поэтому, если оболочка является интерактивной, PS1
она установлена (если только пользователь .bashrc
не удалил ее, чего не могло быть еще наверху .bashrc
, и вы могли бы подумать, что в любом случае это глупо).
Обратное утверждение верно для bash: неинтерактивные экземпляры bash сбрасываются PS1
при запуске. Обратите внимание, что это поведение характерно для bash и, возможно, является ошибкой (почему бы bash -c '… do stuff with $var…'
не работать, когда var
есть PS1
?). Но все версии bash вплоть до 4.4 (включая последнюю версию, как я пишу) делают это.
Многие системы экспортируются PS1
в окружающую среду. Это плохая идея, потому что много разных оболочек используют, PS1
но с другим синтаксисом (например , экранирование приглашений bash полностью отличается от экранирования приглашений zsh ). Но это достаточно широко распространено, так что на практике PS1
его установка не является надежным индикатором интерактивности оболочки. Оболочка может быть унаследована PS1
от среды.
.bashrc
это файл, который bash читает при запуске, когда он интерактивный. Менее известным фактом является то, что bash также читает .bashrc
оболочку входа в систему, и эвристика bash заключает, что это удаленный сеанс (bash проверяет, является ли его родитель rshd
или sshd
). Во втором случае маловероятно, что PS1
это будет установлено в среде, потому что ни один точечный файл еще не запущен.
Однако то, как код использует эту информацию, контрпродуктивно.
.bash_profile
в этой оболочке. Но .bash_profile
это скрипт для входа в систему. Он может запускать некоторые программы, которые предназначены для запуска только один раз за сеанс. Это может переопределить некоторые переменные среды, которые пользователь преднамеренно установил на другое значение перед запуском этой оболочки. Запуск .bash_profile
в оболочке без входа в систему разрушителен..bash_profile
. Но это тот случай, когда загрузка .bash_profile
может быть полезной, потому что неинтерактивная оболочка входа в систему не загружается автоматически /etc/profile
и ~/.profile
.Я думаю, что причина, по которой люди делают это, - для пользователей, которые входят через GUI (очень распространенный случай) и которые .bash_profile
вместо этого помещают свои переменные параметры среды .profile
. Большинство механизмов входа в GUI вызывают, .profile
но не вызывают .bash_profile
(чтение .bash_profile
потребует запуска bash как части запуска сеанса, а не sh). При такой конфигурации, когда пользователь открывает терминал, он получает свои переменные среды. Однако пользователь не получит свои переменные среды в приложениях с графическим интерфейсом, что является очень распространенным источником путаницы. Решением здесь является использование .profile
вместо .bash_profile
установки переменных среды. Добавление моста между .bashrc
и .bash_profile
создает больше проблем, чем решает.
Существует простой, портативный способ проверить, является ли текущая оболочка интерактивной: проверьте, -i
включена ли эта опция .
case $- in
*i*) echo "This shell is interactive";;
*) echo "This shell is not interactive";;
esac
Это полезно .bashrc
для чтения .profile
только в том случае, если оболочка не является интерактивной, то есть противоположна тому, что делает код! Читайте, .profile
если bash является (неинтерактивной) оболочкой для входа, и не читайте ее, если это интерактивная оболочка.
if [[ $- != *i* && -r ~/.profile ]]; then . ~/.profile; fi
[[ -o interactive ]]
(ksh, bash, zsh) или case $- in (*i*) ...; esac
(POSIX)
PS1
если не работает в интерактивном режиме. Это достаточно просто проверить: PS1=cuckoo bash -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
ничего не печатает, а PS1=cuckoo bash -i -c '[ -n "${PS1}" ] && echo "PS1=[${PS1}]"'
печатает значение $PS1
set в ваших файлах запуска bash (строка «кукушка» не печатается).
$-
содержит i
с интерактивной оболочкой.
[ -n "${PS1}" ]
неправильный вызов заходит слишком далеко, ведь он ломается только тогда, когда кто-то экспортирует PS1 (что в своем ответе вы говорите, что это плохая идея, и даже вдумываетесь в причины), и это не влияет В любом случае, bash (поскольку он сбрасывает PS1 и PS2, если оболочка не является интерактивной.) Возможно, лучше использовать слово «обескураженный» или говорить об «ограничениях» подхода. Я не думаю, что это "неправильно" вообще. Если что-то не так экспортирует PS1, это точно! В любом случае, спасибо, что углубились в детали этого.
Кажется, что эта странная концепция является результатом того факта, что bash
она начиналась не как клон оболочки POSIX, а как Bourne Shell
клон.
В результате, интерактивное поведение POSIX (которое $ENV
вызывается для интерактивных оболочек) было добавлено позже bash
и широко не известно.
Существует одна оболочка, которая обеспечивает подобное поведение. Это csh
и гранты csh, которые $prompt
имеют конкретные значения:
$prompt not set non-interactive shell, test $?prompt.
$prompt set but == "" .cshrc called by the which(1) command.
$prompt set and != "" normal interactive shell.
Но это не относится ни к Bourne Shell, ни к POSIX-оболочкам.
Для оболочки POSIX единственный предоставленный метод - поместить код для интерактивных оболочек в файл:
$ENV
это имеет конкретное имя оболочки. Это например
$HOME/.kshrc for the korn shell
$HOME/.bashrc for bash
$HOME/.mkshrc for mksh
$HOME/.shrc for the POSIX Bourne Shell
Другие люди упоминали флаг оболочки -i
, но он не пригоден для надежного программирования. POSIX не требует, чтобы это set -i
работало и не $-
содержало i
интерактивных оболочек. POSIX просто требует, sh -i
чтобы оболочка переводилась в интерактивный режим.
Поскольку переменная $PS1
может быть импортирована из среды, она может иметь значение даже в неинтерактивном режиме. Тот факт, что bash
unset
s PS1
в любой неинтерактивной оболочке не предоставляется стандартом и не делается никакой другой оболочкой.
Таким образом, чистое программирование (даже с bash
) состоит в том, чтобы поместить команды для интерактивных оболочек $HOME/.bashrc
.
Сначала я расскажу о том, что Debian, а также большую часть времени Ubuntu устанавливает для bash. И последнее касается других систем.
В настройках файлов запуска оболочки есть много мнений.
У меня тоже есть свое мнение, но я постараюсь показать существующие примеры правильных настроек.
Я буду использовать debuan, так как примеры его файлов довольно легко найти.
И Debian активно используется, поэтому настройки были хорошо протестированы,
Только чтобы узнать, является ли оболочка интерактивной.
По умолчанию /etc/profile
в Debian и Ubuntu (из / usr / share / base-files / profile):
if [ "${PS1-}" ]; then
if [ "${BASH-}" ] && [ "$BASH" != "/bin/sh" ]; then
If читается: если интерактивный (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 и одна альтернатива.
Настройки, о которых вы сообщаете, следует избегать.
Порядок (от системных настроек и более конкретных пользовательских настроек (для Баш)) является /etc/profile
, /etc/bash.bashrc
, ~/.profile
и , наконец ~/.bashrc
. Это помещает самые широкие эффекты (и для большего количества оболочек) в /etc/profile
(который принадлежит root), за которым следует /etc/bash.bashrc
(который также принадлежит root), но влияет только на bash. Затем перейдите к личным настройкам $HOME
, первый ~/.profile
для большинства оболочек и ~/.bashrc
(почти эквивалентный ~/.bash_profile
), специфичный только для bash.
Поэтому неправильно источник ~/.bashrc
в ~/.profile
это трансформирует специфичный для установки Баша к более общим , что пользователю затрагивают более оболочки . За исключением случаев, когда сделано так :
# ~/.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
(или наоборот), и в этом случае можно использовать проверку интерактивной оболочки.
( export PS1='abc$ '; bash -c 'echo "[$PS1]"' )
которой просто печатает[]
. Кажется , ЗШ не делает то же самое, по крайней мере , из эксперимента ... В любом случае, намерение из[ -n "$PS1" ]
, чтобы проверить , является ли интерактивной оболочкой или нет.