Какие области могут иметь переменные оболочки?

Я просто столкнулся с проблемой, которая показывает мне, что я не вижу смысла в переменных оболочки.

Я пытался использовать bundle install, который является командой Ruby, которая использует значение $GEM_HOME, чтобы выполнить свою работу. Я установил $GEM_HOME, но команда проигнорировала это значение, пока не использовала export, как в export GEM_HOME=/some/path.

Я читал, что это делает переменную как-то «глобальной» (также известной как переменная среды ), но я не понимаю, что это значит. Я знаю о глобалах в программировании, но не в разных программах.

Кроме того, учитывая, что моя настройка таких переменных применима только к текущему сеансу оболочки, как бы установить их для, скажем, демонаризованного процесса?

Какие области могут иметь переменные оболочки?

33 голоса | спросил Nathan Long 24 SatEurope/Moscow2011-12-24T07:07:11+04:00Europe/Moscow12bEurope/MoscowSat, 24 Dec 2011 07:07:11 +0400 2011, 07:07:11

2 ответа


9

Они обрабатываются процессом

Другие ответчики помогли мне понять, что область оболочки оболочки - это процессы и их потомки .

Когда вы вводите в командной строке команду типа ls, вы фактически выполняете процесс для запуска ls. Новый процесс имеет свою оболочку в качестве родителя.

Любой процесс может иметь свои собственные «локальные» переменные, которые не передаются дочерним процессам. Он также может устанавливать переменные среды. Использование export создает переменную окружения. В любом случае несвязанные процессы (сверстники оригинала) не будут видеть переменную; мы контролируем только то, что видят дочерние процессы.

Предположим, что у вас есть оболочка bash, которую мы назовем A. Вы вводите bash, который создает оболочку bash дочернего процесса, который мы назовем B. Все, что вы назовете export on в A, все равно будет установлено в B.

Теперь, в B, вы говорите FOO=b. Будет одна из двух вещей:

  • Если B не получил (от A) переменную среды, называемую FOO, она создаст локальную переменную. Дети B не получат его (если B не называет export).
  • Если B сделал , получив (от A) переменную окружения, запрограммированную FOO, она будет измените его для себя и его потомство раздвоенных детей . Дети из B будут видеть значение, которое B назначено. Однако это вообще не повлияет на A.

Вот быстрая демонстрация.

FOO=a      # set "local" environment variable
echo $FOO  # 'a'
bash       # forks a child process for the new shell
echo $FOO  # not set
exit       # return to original shell
echo $FOO  # still 'a'

export FOO # make FOO an environment variable
bash       # fork a new "child" shell
echo $FOO  # outputs 'a'
FOO=b      # modifies environment (not local) variable
bash       # fork "grandchild" shell
echo $FOO  # outputs 'b'
exit       # back to child shell
exit       # back to original shell
echo $FOO  # outputs 'a'

Все это объясняет мою первоначальную проблему: я установил GEM_HOME в свою оболочку, но когда я позвонил bundle install, который создал дочерний процесс. Поскольку я не использовал export, дочерний процесс не получил код GEM_HOME

Un-экспортерах

Вы можете «экспортировать» переменную - не передавать ее детям - с помощью export -n FOO.

export FOO=a   # Set environment variable
bash           # fork a shell
echo $FOO      # outputs 'a'
export -n FOO  # remove environment var for children
bash           # fork a shell
echo $FOO      # Not set
exit           # back up a level
echo $FOO      # outputs 'a' - still a local variable
ответил Nathan Long 5 Jam1000000amThu, 05 Jan 2012 00:34:56 +040012 2012, 00:34:56
23

По крайней мере, в ksh и bash, переменные могут иметь три области, а не два , как и все оставшиеся ответы.

В дополнение к экспортированной (то есть среде) переменной и оболочке невозвращенных областей переменных, есть также третий более узкий для локальных переменных функции.

Переменные, объявленные в функциях оболочки с маркером typeset, видны только внутри функций, которые они объявлены, и в (под) функциях, называемых оттуда.

Этот код ksh /bash

# Create a shell script named /tmp/show that displays the scoped variables values.    
echo 'echo [$environment] [$shell] [$local]' > /tmp/show
chmod +x /tmp/show

# Function local variable declaration
function f
{
    typeset local=three
    echo "in function":
    . /tmp/show 
}

# Global variable declaration
export environment=one

# Unexported (i.e. local) variable declaration
shell=two

# Call the function that creates a function local variable and
# display all three variable values from inside the function
f

# Display the three values from outside the function
echo "in shell":
. /tmp/show 

# Display the same values from a subshell
echo "in subshell":
/tmp/show

# Display the same values from a disconnected shell (simulated here by a clean environment start)
echo "in other shell"
env -i /tmp/show 

производит этот вывод:

in function:
[one] [two] [three]
in shell:
[one] [two] []
in subshell:
[one] [] []
in other shell
[] [] []

Как вы можете видеть, экспортированная переменная отображается из первых трех местоположений, нераспределенные переменные не отображаются за пределами текущей оболочки, а локальная переменная функции не имеет значения вне самой функции. Последний тест не показывает никаких значений, потому что экспортированные переменные не разделяются между оболочками, то есть они могут быть наследуемыми, а потом унаследованное значение не может быть затронуто родительской оболочкой.

Обратите внимание, что это последнее поведение сильно отличается от Windows, где вы можете использовать системные переменные, которые полностью глобальны и совместно используются всеми процессами.

ответил jlliagre 5 Jam1000000amThu, 05 Jan 2012 10:03:55 +040012 2012, 10:03:55

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

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

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