Из того, что я могу сказать printenv
переменные среды дисплеев, но почему я не вижу другие переменные как PS1
для настройки приглашения оболочки?
Что точно printenv
вывод и почему это не берет PS1
? Есть ли более всесторонняя выходная команда, которая делает больше, чем printenv
?
Поэтому PS1
обычно не экспортируется.
Переменные среды используются для установки среды выполнения дочерних процессов; с тех пор PS1
только действительно имеет значение в интерактивной оболочке, обычно нет никакой точки, экспортирующей его - это - просто плоскость переменная оболочки .
при запуске интерактивного дочернего элемента оболочка , затем она считает и установит PS1
от файла ресурсов оболочки такой как ~/.bashrc
, Если Вы export PS1
затем Вы будете видеть его в эти printenv
вывод. Кроме того, Вы видите простые переменные оболочки с помощью удара, встроенного set
, как описано здесь , Как перечислить все имена переменных и их текущие значения?
Есть ли более всесторонняя выходная команда, которая делает больше, чем
printenv
?
printenv
печать только переменные среды, которые можно считать преимуществом. Но если Вы хотите распечатать переменные оболочки также, использовать echo "$x"
(или printf '%s\n' "$x"
, который более устойчив) вместо printenv x
.
объяснение steeldriver этих проблем полезно и корректно, но я представляю тему в другом отношении здесь.
printenv
внешняя команда - не встроенный в Вашу оболочку, но отдельную программу от Вашей оболочки. Это показывает свои собственные переменные среды, которые являются теми, которые это наследовало от оболочки, которую Вы используете для выполнения его. Однако оболочки не передают все свои переменные в среды их подпроцессов. Вместо этого они поддерживают различие, между которым переменные являются переменными среды и которые не являются. (Те, которые не являются, часто являются переменными оболочки вызова.)
Чтобы видеть, как это работает, попробуйте эти команды, в которые включают (
)
таким образом, они действуют independently1 друг друга. Индивидуально, каждая из этих команд работает то же при выполнении его без (
)
, но переменные, которые Вы создаете в более ранних командах, все еще существовали бы в более поздних командах. Выполнение команд в подоболочках предотвращает это.
Создание новой переменной, затем выполнение внешней команды, не передают переменную в среду команды. Кроме необычного случая, что у Вас уже есть переменная среды x
, эта команда не производит вывода:
(x=foo; printenv x)
Переменная присвоена в оболочке, все же. Эта команда выводы foo
:
(x=foo; echo "$x")
Оболочка поддерживает синтаксис для передачи переменной в среду команды, не влияя на среду текущей оболочки. Это производит foo
:
x=foo printenv x
(Который работает в подоболочке также, конечно-(x=foo printenv x)
- но я показал его без (
)
потому что при использовании того синтаксиса ничто не установлено для текущей оболочки, так использование подоболочки является ненужным, чтобы препятствовать тому, чтобы были затронуты последующие команды.)
Это печатает foo
, затем печать bar
:
(x=bar; x=foo printenv x; echo "$x")
При экспорте переменной она автоматически передается в среды всех последующих внешних команд, выполненных от той же оболочки. export
команда делает это. Можно использовать его перед определением переменной после определения его, или можно даже определить переменную в export
управляйте собой. Все они печатают foo
:
(x=foo; export x; printenv x)
(export x; x=foo; printenv x)
(export x=foo; printenv x)
Существует нет unexport
команда. Даже при том, что можно экспортировать переменную прежде, чем установить его, сбрасывание переменной также не экспортирует его, который должен сказать, что это ничего не печатает вместо печати bar
:
(x=foo; export x; unset x; x=bar; printenv x)
Но изменение значения переменной после экспорта его действительно влияет на экспортируемое значение. Это печатает foo
, затем bar
:
(export x=foo; printenv x; x=bar; printenv x)
Как другие процессы, Ваша оболочка сама наследовала переменные среды от своего родительского процесса. Такие переменные присутствуют первоначально в среде Вашей оболочки, и они автоматически экспортируются - или остаются экспортируемыми, если Вы принимаете решение думать о ней тот путь. Это печатает foo
(помните, VAR=val cmd
выполнения cmd
с VAR
набор к val
в его среде):
x=foo bash -c 'printenv x'
Набор переменных в дочерних процессах не влияет на родительский процесс, даже если они экспортируются. Это печатает foo
(нет bar
):
(x=foo; bash -c 'export x=bar'; echo "$x")
Подоболочка является также дочерним process2; это также печатает foo
:
(x=foo; (export x=bar); echo "$x")
Это должно сделать более ясным, почему я включил большинство этих команд в (
)
выполнять их в подоболочках.
Подоболочки являются особенными, все же. В отличие от других подпроцессов, таких как созданные, когда Вы выполняете внешнюю команду как printenv
или bash
, подоболочка наследовала большую часть состояния своей родительской оболочки. В частности, подоболочки наследовали даже переменные, которые не экспортируются. Так же, как (x=foo; echo "$x")
печать foo
, делает (x=foo; (echo "$x"))
.
Неэкспортируемая переменная все еще не экспортируется в подоболочке - если Вы не экспортируете ее - так, так же, как (x=foo; printenv x)
печать ничто, делает (x=foo; (printenv x))
.
Подоболочка является специальным видом подпроцесса, который является оболочкой. Не все подпроцессы, которые являются оболочками, являются подоболочками. Оболочка создается путем выполнения bash
не подоболочка, и она не наследовала неэкспортируемые переменные. Таким образом, эта команда печатает пустую строку (потому что echo
печатает новую строку, даже когда названо с пустым аргументом):
(x=foo; bash -c 'echo "$x"')
PS1
не переменная среды (и обычно не должен быть один),Наконец, что касается почему быстрые переменные как PS1
переменные оболочки, но не переменные среды, причины:
PS1
к новой оболочке обычно перестал бы работать, потому что оболочка обычно сбрасывает PS1
.Точка № 3 заслуживает немного большего количества объяснения, хотя, если Вы никогда не пытаетесь сделать PS1
переменная среды, затем Вы, вероятно, не должны действительно знать детали.
PS1
.Когда неинтерактивная оболочка Bash запускает, это сбросы always3 PS1
. Это печатает пустую строку (нет foo
):
PS1=foo bash -c 'echo "$PS1"'
Чтобы проверить, что это на самом деле сброшено, и не только набор, но и пустое, можно выполнить это, которое печатает unset
:
PS1=foo bash -c 'if [[ -v PS1 ]]; then echo set; else echo unset; fi'
Чтобы проверить, что это независимо от другого поведения запуска, Вы могли попытаться передать любую комбинацию --login
, --norc
, или --posix
прежде -c
, или установка BASH_ENV
к пути некоторого сценария (например, BASH_ENV=~/.bashrc PS1=foo bash ...
), или ENV
если Вы передали --posix
. Ни в коем случае не делает неинтерактивный сбой оболочки Bash для сбрасывания PS1
.
То, что это означает, является этим, если Вы экспортируете PS1
и выполненный неинтерактивная оболочка, которая сама выполняет интерактивную оболочку, которую она не установит, имеет PS1
оцените Вы первоначально устанавливаете. Поэтому - и также потому что другие оболочки помимо Bash (как Ksh) все не ведут себя тот же путь и способ, которым Вы пишете PS1
поскольку Bash не всегда работает на те оболочки - я рекомендую против попытки сделать PS1
переменная среды. Просто редактирование ~/.bashrc
для установки безотносительно подсказки, Вы хотите.
PS1
.С другой стороны, если Вы сбрасываете PS1
и выполненный интерактивная оболочка Bash, даже если Вы препятствуете тому, чтобы он выполнил команды из сценариев запуска путем передачи --norc
, это все еще автоматически установит PS1
к значению по умолчанию. Выполнение env -u PS1 bash --norc
дает Вам интерактивную оболочку Bash с PS1
набор к \s-\v\$
. Так как Bash расширяется \s
к названию оболочки и \v
к номеру версии это показывает bash-4.3$
как подсказка на Ubuntu 16.04 LTS. Отметьте ту установку PS1
оцените, поскольку пустая строка не является тем же как сбрасыванием его. Как объяснено ниже, работая PS1= bash
дает Вам интерактивную оболочку со странным поведением запуска. Необходимо постараться не экспортировать PS1
когда это установлено на пустую строку в практическом применении, если Вы не понимаете и хотите то поведение.
Однако, если Вы устанавливаете PS1
и выполненный интерактивная оболочка Bash - и это не становится сброшенным посреднической неинтерактивной оболочкой - это сохранит то значение... до сценария запуска как глобальное /etc/profile
(для оболочек входа в систему) или /etc/bash.bashrc
, или Ваше в расчете на пользователя ~/.profile
, ~/.bash_login
, или ~/.bash_profile
(все для оболочек входа в систему) или ~/.bashrc
сброс это.
Даже если Вы редактируете те файлы, чтобы препятствовать тому, чтобы они установили PS1
- который, в случае /etc/profile
и /etc/bash.bashrc
, Я рекомендую против выполнения так или иначе, так как они влияют на всех пользователей - Вы не можете действительно полагаться на это. Как упомянуто выше, интерактивные оболочки, запущенные с неинтерактивных оболочек, не будут иметь PS1
, если Вы не должны были сбрасывать и реэкспортировать его в неинтерактивной оболочке. Кроме того, необходимо думать дважды прежде, чем сделать это, потому что это характерно для кода оболочки (включая функции оболочки, которые Вы, возможно, определили) проверять PS1
определить, работает ли оболочка это в, является интерактивным или неинтерактивным.
PS1
распространенный способ состоит в том, чтобы определить, является ли текущая оболочка интерактивной.Поэтому для неинтерактивного Bash shells4 настолько важно сбросить PS1
автоматически. Как разделяют 6.3.2, этот Интерактивный Shell? из Bash говорится в справочнике:
[S] сценарии tartup могут исследовать переменную
PS1
; это сброшено в неинтерактивных оболочках и установлено в интерактивных оболочках.
Чтобы видеть, как это работает, посмотрите пример там. Или проверьте реальное использование в Ubuntu. По умолчанию, /etc/profile
в Ubuntu включает:
if [ "$PS1" ]; then
if [ "$BASH" ] && [ "$BASH" != "/bin/sh" ]; then
# The file bash.bashrc already sets the default PS1.
# PS1='\h:\w\$ '
if [ -f /etc/bash.bashrc ]; then
. /etc/bash.bashrc
fi
else
if [ "`id -u`" -eq 0 ]; then
PS1='# '
else
PS1='$ '
fi
fi
fi
/etc/bash.bashrc
, то, которое не должно делать ничего вообще, когда оболочка является неинтерактивной, имеет:
# If not running interactively, don't do anything
[ -z "$PS1" ] && return
Достигнуть той же цели, /etc/skel/.bashrc
, который копируется в корневые каталоги пользователей, когда их учетные записи создаются (так Ваш ~/.bashrc
вероятно, подобно), имеет:
# If not running interactively, don't do anything
case $- in
*i*) ;;
*) return;;
esac
Это - другой распространенный способ проверить, является ли оболочка интерактивной: посмотрите если текст, полученный путем расширения специального параметра -
(путем записи $-
) содержит букву i
. Обычно это имеет точно тот же эффект. Предположим, однако, что Вы не изменили код, показанный выше этого, появляется по умолчанию в сценариях запуска Bash в Ubuntu, и что:
PS1
как переменная среды, иЗатем /etc/profile
(если это - оболочка входа в систему), или /etc/bash.bashrc
не выполнит команды, которые они обычно выполняют для интерактивных оболочек. ~/.bashrc
все еще будет.
Если Вы хотите проверить, является ли оболочка интерактивной при помощи PS1
и получите правильный ответ даже когда PS1
установлен, но пуст, можно использовать [[ -v PS1 ]]
или [ -v PS1 ]
/test -v PS1
вместо этого. Обратите внимание, однако, что [[
ключевое слово, и -v
тест [
и test
окружите builtins, конкретны к Bash. Не все другие оболочки стиля Границы принимают их. Таким образом, Вы не должны использовать их в сценариях как ~/.profile
и /etc/profile
это могло бы работать в других оболочках (или менеджером по оформлению, когда Вы входите в систему графически), если у Вас нет чего-то еще в сценарии, который проверяет, какая оболочка выполняет и только выполняет определенные для Bash команды, когда та оболочка является Bash (например, путем проверки $BASH_VERSION
).
1 Эта статья объясняет подоболочки подробно. 3.2.4.3 Группировка Команд справочника Bash объясняет (
)
синтаксис.
2 Примечания, что существуют обстоятельства под который команды, выполненные в подоболочках даже с (
)
синтаксис не используется. Например, когда у Вас есть команды, разделенные |
в конвейере Bash выполняет каждого из них в подоболочке (если lastpipe
опция оболочки установлена).
3 За исключением подоболочек. Возможно это даже не исключение, так как подоболочки не "запускают" в обычном смысле, который мы имеем в виду, когда мы говорим об этом. (У них действительно нет значительного поведения инициализации.) Отмечают это, когда Вы работаете bash
- с или без аргументов - в оболочке Bash, которая создает подпроцесс, который является оболочкой, но это не подоболочка.
4 Примечания, что не все оболочки - даже все оболочки стиля Границы - ведут себя этот путь. Но Bash делает, и коду Bash, включая код в сценариях запуска, очень свойственно полагаться на него.