Відповіді:
Це перевірка, чи оболонка інтерактивна чи ні. У цьому випадку ~/.bash_profile
файл можна розміщувати лише в тому випадку, якщо оболонка інтерактивна.
Дивіться "Чи інтерактивна ця оболонка?" у посібнику з bash, де цитується ця конкретна ідіома. (Також рекомендується перевірити, чи оболонка є інтерактивною, перевіривши, чи $-
містить спеціальна змінна i
символ, що є кращим підходом до цієї проблеми.)
bash
знімає PS1, коли неінтерактивна (помилка в попередньому коментарі) є помилкою IMO, PS1 не є специфічною для змінного струму змінною. Це єдина оболонка, яка робить це (хоча yash
також встановлює PS1
значення за замовчуванням, навіть коли не є інтерактивним).
[[ $- = *i* ]] && source ~/.bash_profile
).
[ -n "${PS1}" ]
, але я все-таки оновив свою відповідь, щоб підкреслити, що посібник з bash також пропонує / рекомендує перевірити, $-
щоб визначити, чи оболонка є інтерактивною, я сподіваюся, ви знайдете, що покращує відповідь. Ура!
Це широко розповсюджений спосіб перевірити, чи інтерактивна оболонка. Слідкуйте за тим, щоб він працював лише в баш, він не працює з іншими оболонками. Так що це нормально (якщо нерозумно) для .bashrc
, але він би не працював .profile
(що читається sh, а bash - лише одна з можливих реалізацій sh, а не найпоширеніша).
Інтерактивна оболонка встановлює змінну оболонкиPS1
на рядок підказок за замовчуванням. Отже, якщо оболонка інтерактивна, PS1
встановлюється (якщо тільки користувач її .bashrc
не видалив, що ще не могло статися вгорі .bashrc
, і ви можете вважати, що це все-таки дурне).
Зворотне і в bash: неінтерактивні екземпляри bash unset PS1
під час їх запуску. Зауважте, що така поведінка характерна для bash, і, ймовірно, помилка (чому б bash -c '… do stuff with $var…'
не працювати, коли var
є PS1
?). Але всі версії bash аж до 4.4 (включаючи останню версію, як я пишу) роблять це.
Багато систем експортують PS1
у навколишнє середовище. Це погана ідея, оскільки багато різних оболонок використовують, PS1
але з іншим синтаксисом (наприклад , швидкі втечі башів повністю відрізняються від швидких втечі zsh ). Але це досить поширено, що на практиці бачення PS1
встановленого не є надійним показником того, що оболонка є інтерактивною. Оболонка, можливо, успадкувала PS1
від навколишнього середовища.
.bashrc
це файл, який баш читає при запуску, коли він інтерактивний. Менш відомий факт полягає в тому, що bash також читає .bashrc
оболонку входу, і евристика bash робить висновок, що це віддалений сеанс (bash перевіряє, чи є його батьківський rshd
або sshd
). У цьому другому випадку навряд чи це PS1
було б встановлено в оточенні, оскільки ще не запущено жодного файлу точок.
Однак спосіб використання кодом цієї інформації контрпродуктивний.
.bash_profile
в цій оболонці. Але .bash_profile
це сценарій часу входу. Він може запускати деякі програми, які призначені для запуску лише один раз за сеанс. Це може змінити деякі змінні середовища, які користувач навмисно встановив на інше значення перед запуском оболонки. Запуск .bash_profile
у оболонці без входу є руйнівним..bash_profile
. Але це той випадок, коли завантаження .bash_profile
може бути корисним, оскільки неінтерактивна оболонка входу не завантажується автоматично /etc/profile
і ~/.profile
.Я думаю, що люди це роблять в тому, що користувачі, які входять у систему через графічний інтерфейс (дуже поширений випадок) і .bash_profile
замість того, щоб замінити їх налаштування змінної середовища .profile
. Більшість механізмів входу в графічний інтерфейс викликають, .profile
але не .bash_profile
(для читання .bash_profile
потрібен запуск bash як частина запуску сеансу, а не sh). При такій конфігурації, коли користувач відкриє термінал, він отримає свої змінні середовища. Однак користувач не отримає своїх змінних оточуючих середовищ у додатках GUI, що є дуже поширеним джерелом плутанини. Рішення тут полягає у використанні .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
встановлене у ваших файлах запуску bash (він не буде друкувати рядок "зозуля").
$-
містить i
з інтерактивною оболонкою.
[ -n "${PS1}" ]
неправильним є занадто далеко, адже він порушується лише тоді, коли хтось експортує PS1 (що у вашій відповіді ви говорите, що це погана ідея і навіть вникати в причини), і це не впливає все-таки бійся (оскільки він знімає 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.
Але це не стосується ні оболонки Борна, ні снарядів 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
Якщо читається: якщо інтерактивна (встановлено стандарт 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
(який належить корінь), а далі /etc/bash.bashrc
(який також належить корінь), але впливає лише на bash. Тоді з’являються особисті налаштування $HOME
, перший - ~/.profile
для більшості оболонок і ~/.bashrc
(майже еквівалентний ~/.bash_profile
), специфічний лише для баш.
Тому неправильно джерело ~/.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]"' )
якого просто друкується[]
. Здається, zsh не робить те саме, принаймні з експерименту ... У будь-якому випадку, намір[ -n "$PS1" ]
полягає в тому, щоб перевірити, чи оболонка є інтерактивною чи ні.