Ответы:
Это проверяет, является ли оболочка интерактивной или нет. В этом случае, только поиск ~/.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}]"'печатает значение $PS1set в ваших файлах запуска 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 unsets 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" ], чтобы проверить , является ли интерактивной оболочкой или нет.