переменная среды, не найденная в gdb [duplicate]

В Java все находится в форме класса.

Если вы хотите использовать любой объект, тогда у вас есть две фазы:

  1. Объявить
  2. Инициализация

Пример:

  • Объявление: Object a;
  • Инициализация: a=new Object();

То же самое для концепции массива

  • Объявление: Item i[]=new Item[5];
  • Инициализация: i[0]=new Item();

Если вы не дают секцию инициализации, тогда возникает NullpointerException.

693
задан Will Vousden 5 November 2013 в 18:15
поделиться

14 ответов

export делает переменную доступной для подпроцессов.

То есть,

export name=value

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

name=value

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

Важно отметить, что экспорт переменной не делает ее доступной для родительских процессов. То есть, указание и экспорт переменной в порожденном процессе не делает ее доступной в процессе ее запуска.

780
ответ дан Brian Agnew 18 August 2018 в 06:36
поделиться
  • 1
    В частности, экспорт делает переменную доступной для дочерних процессов через среду. – Beano 21 July 2009 в 14:35
  • 2
    Я бы также добавил, что если экспорт находится в файле, который у вас есть "source & quot; (например, имя файла), то он также экспортирует его в рабочую среду. – rogerdpack 17 September 2013 в 23:44
  • 3
    @rogerdpack вы не можете сделать это без экспорта? cat & gt; blah\n a = hi\n. л; echo $ a; выводит «привет» для меня. – David Winiecki 1 October 2013 в 00:49
  • 4
    Для этого есть один крайний случай; name=value command делает , чтобы переменная была доступна в подпроцессе command. – Oliver Charlesworth 23 December 2015 в 12:09
  • 5
    Кажется, что это работает так, что если переменная уже является экспортируемой переменной, вы можете назначить ее без export, и изменение будет видимым для фонового процесса. (Я тестировал переменную PATH в сценариях bash и dash). – jarno 31 January 2016 в 11:33

Чтобы проиллюстрировать, что говорят другие ответы:

$ foo="Hello, World"
$ echo $foo
Hello, World
$ bar="Goodbye"
$ export foo
$ bash
bash-3.2$ echo $foo
Hello, World
bash-3.2$ echo $bar

bash-3.2$ 
194
ответ дан 4wk_ 18 August 2018 в 06:36
поделиться

По умолчанию переменные, созданные в скрипте, доступны только текущей оболочке; дочерние процессы (суб-оболочки) не будут иметь доступ к значениям, которые были установлены или изменены. Разрешая дочерним процессам видеть значения, требуется использовать команду export.

0
ответ дан Amjad 18 August 2018 в 06:36
поделиться

Было сказано, что нет необходимости экспортировать в bash, когда нерестуют подоболочки, в то время как другие говорят прямо противоположное. Важно отметить разницу между подоболочками (те, которые созданы (), ``, $() или циклы) и подпроцессы (процессы, вызываемые по имени, например, литерал bash, отображаемый в вашем скрипте ). Подседки будут иметь доступ ко всем переменным от родителя, независимо от их экспортируемого состояния. С другой стороны, подпроцессы будут видеть только экспортированные переменные. Что общего в этих двух конструктах, так это то, что ни одна из них не может передавать переменные обратно в родительскую оболочку.

$ noexport=noexport; export export=export; (echo subshell: $noexport $export; subshell=subshell); bash -c 'echo subprocess: $noexport $export; subprocess=subprocess'; echo parent: $subshell $subprocess
subshell: noexport export
subprocess: export
parent:

Есть еще один источник путаницы: некоторые считают, что подпроцессы «раздвоенные» - это те, t неэкспортируемые переменные. Обычно fork () s сразу следует за exec () s, и поэтому кажется, что fork () - это то, что нужно искать, в то время как на самом деле это exec (). Вы можете запускать команды без fork () сначала с помощью команды exec, и процессы, запущенные этим методом, также не будут иметь доступа к невыгруженным переменным:

$ noexport=noexport; export export=export; exec bash -c 'echo execd process: $noexport $export; execd=execd'; echo parent: $execd
execd process: export

Обратите внимание, что мы не видим parent: на этот раз, потому что мы заменили родительскую оболочку командой exec, поэтому для выполнения этой команды ничего не осталось.

43
ответ дан Benjamin W. 18 August 2018 в 06:36
поделиться
  • 1
    Отличное резюме – Will Sheppard 6 May 2016 в 15:05
  • 2
    Очень хороший ответ, чтобы упомянуть разницу между подоболочками и подпроцессами. Другое дело: хотя подоболочки могут читать все переменные от родителя, он не может изменить значение переменных в родительском. – PickBoy 27 February 2017 в 07:30
  • 3
    Я никогда не видел цикл, который (сам по себе) создал подоболочку; OTOH конвейер делает (всегда для частей, отличных от последних, иногда для последних в зависимости от вашей оболочки, версии и опций). Backgrounding (&) также создает подоболочку. – dave_thompson_085 18 September 2017 в 23:38

export NAME=value для настроек и переменных, имеющих смысл для подпроцесса.

NAME=value для временных или циклических переменных, приватных для текущего процесса оболочки.

Более подробно export отмечает имя переменной в среде, которая копирует подпроцессы и их подпроцессы при создании. Никакое имя или значение не копируются обратно из подпроцесса.

  • Общей ошибкой является размещение пространства вокруг знака равенства:
    $ export FOO = "bar"  
    bash: export: `=': not a valid identifier
    
  • Подпроцессом видна только экспортированная переменная (B):
    $ A="Alice"; export B="Bob"; echo "echo A is \$A. B is \$B" | bash
    A is . B is Bob
    
  • Изменения в подпроцессе не меняют основную оболочку:
    $ export B="Bob"; echo 'B="Banana"' | bash; echo $B
    Bob
    
  • Переменные, отмеченные для экспорта, имеют значения, скопированные при создании подпроцесса:
    $ export B="Bob"; echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash &
    [1] 3306
    $ B="Banana"; echo '(sleep 30; echo "Subprocess 2 has B=$B")' | bash 
    Subprocess 1 has B=Bob
    Subprocess 2 has B=Banana
    [1]+  Done         echo '(sleep 30; echo "Subprocess 1 has B=$B")' | bash
    
  • Только экспортируемые переменные становятся частью среды (man environ):
     $ ALICE="Alice"; export BOB="Bob"; env | grep "ALICE\|BOB"
     BOB=Bob
    

Итак, теперь это должно быть так же ясно, как солнце лета! Благодаря Brain Agnew, alexp и William Prusell.

26
ответ дан Charles Merriam 18 August 2018 в 06:36
поделиться

Два из создателей UNIX, Брайан Керниган и Роб Пайк объясняют это в своей книге «Окружающая среда программирования UNIX». Google для названия, и вы легко найдете версию в формате pdf.

Они обращаются к переменным оболочки в разделе 3.6 и фокусируются на использовании команды export в конце этого раздела:

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

2
ответ дан Dan Carter 18 August 2018 в 06:36
поделиться

В принятом ответе подразумевается это, но я хотел бы сделать явным связь с встроенными оболочками оболочки:

Как уже упоминалось, export сделает переменную доступной для как снаряд, так и дети. Если export используется , а не , переменная будет доступна только в оболочке, и только shell встроены могут получить к ней доступ.

То есть

tango=3
env | grep tango # prints nothing, since env is a child process
set | grep tango # prints tango=3 - "type set" shows `set` is a shell builtin
5
ответ дан flow2k 18 August 2018 в 06:36
поделиться

export сделает доступную переменную доступной для всех оболочек, выделенных из текущей оболочки.

9
ответ дан John T 18 August 2018 в 06:36
поделиться

Следует отметить, что вы можете экспортировать переменную, а затем изменить значение. Измененное значение переменной будет доступно для дочерних процессов. После того как экспорт был установлен для переменной, вы должны сделать export -n <var>, чтобы удалить свойство.

$ K=1
$ export K
$ K=2
$ bash -c 'echo ${K-unset}'
2
$ export -n K
$ bash -c 'echo ${K-unset}'
unset
9
ответ дан Mateusz Piotrowski 18 August 2018 в 06:36
поделиться
  • 1
    Спасибо, это именно то, что я искал, потому что я видел сценарий, который использовал переменные среды, а затем «реэкспортировал». они с новым значением, и мне было интересно, если это необходимо. – Mike Lippert 1 June 2016 в 16:28
  • 2
    Этот пример неверен. Здесь "echo $K" расширяется до echo 2 в любом случае до выполнения дочернего Bash. Если вы хотите доказать свою точку зрения, используйте одинарные кавычки, чтобы ребенок Bash увидел $K и расширил его сам. – eepp 4 November 2016 в 19:07
  • 3
    @eepp Я только что отредактировал ответ, чтобы исправить эту проблему. – Carlo Wood 12 February 2017 в 13:43

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

Программа может получить доступ к своим переменным среды через этот UNIX API:

  • char *getenv(const char *name);
  • int setenv(const char *name, const char *value, int override);
  • int unsetenv(const char *name);

Процессы также наследуют переменные среды из родительских процессов. Операционная система отвечает за создание копии всех «envars» в момент создания дочернего процесса.

Bash , среди других оболочек, может устанавливать свои переменные среды на пользовательский запрос. Это то, что существует для export.

export - это команда Bash для установки переменной среды для Bash. Все переменные, заданные этой командой, будут наследоваться всеми процессами, которые этот Bash создавал.

Подробнее о Среда в Bash

Другой вид переменной в Bash является внутренней переменной. Поскольку Bash - это не просто интерактивная оболочка, она на самом деле является интерпретатором сценария, так как любой другой интерпретатор (например, Python) способен хранить свой собственный набор переменных. Следует отметить, что Bash (в отличие от Python) поддерживает только строковые переменные.

Обозначение для определения переменных Bash - name=value. Эти переменные остаются внутри Bash и не имеют ничего общего с переменными среды, хранящимися в операционной системе.

Подробнее о Параметры оболочки (включая переменные)

Также стоит отметить что, согласно справочному руководству Bash:

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


Чтобы суммировать вещи:

  • export используется для установки переменной среды в операционной системе. Эта переменная будет доступна для всех дочерних процессов, созданных с помощью текущего процесса Bash.
  • Обозначение переменной Bash (name = value) используется для установки локальных переменных, доступных только текущему процессу bash
  • Обозначение переменной Bash, префикс другой команды, создает переменную среды только для области действия этой команды.
6
ответ дан progalgo 18 August 2018 в 06:36
поделиться
  • 1
    bash vars не поддерживают столько типов, как Python, но имеют строковый, целочисленный и два типа массива («индексированный» / традиционный и «ассоциативный», который похож на awk-массив, perl-хэш или Python-dict). Другие оболочки меняются; <строка> переносится . – dave_thompson_085 18 September 2017 в 23:58

Хотя это явно не упоминается в обсуждении, НЕ НЕОБХОДИМО использовать экспорт при создании нерегулярной оболочки изнутри bash, поскольку все переменные копируются в дочерний процесс.

1
ответ дан Scott 18 August 2018 в 06:36
поделиться
  • 1
    Пожалуйста, объясните, как то, что вы говорите, кажется, прямо противоречит ответам с примерами выше. – Mike Lippert 23 November 2013 в 18:19
  • 2
    Это правильный путь, если вы не хотите, чтобы переменные экспортировались глобально, но доступны только для подпроцесса! Спасибо. – jtblin 6 July 2014 в 03:09

Вот еще один пример:

VARTEST="value of VARTEST" 
#export VARTEST="value of VARTEST" 
sudo env | grep -i vartest 
sudo echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}" 
sudo bash -c 'echo ${SUDO_USER} ${SUDO_UID}:${SUDO_GID} "${VARTEST}"'  

Только с помощью экспорта VARTEST значение VARTEST доступно в sudo bash -c '...'!

Дополнительные примеры см. в:

3
ответ дан user 18 August 2018 в 06:36
поделиться

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

Если я это сделаю:

$ MYNAME=Fred
$ export OURNAME=Jim

, тогда в env появляется только $ OURNAME. Переменная $ MYNAME отсутствует в env.

$ env | grep NAME
OURNAME=Jim

, но переменная $ MYNAME существует в оболочке

$ echo $MYNAME
Fred
2
ответ дан Will 18 August 2018 в 06:36
поделиться

Другие ответили, что экспорт делает переменную доступной для подоболочек, и это правильно, но просто побочный эффект. Когда вы экспортируете переменную, она помещает эту переменную в среду текущей оболочки (т.е. оболочка вызывает putenv (3) или setenv (3)). Окружающая среда процесса наследуется через exec, делая переменную видимой в подоболочках.

Редактировать (с перспективой на 5 лет): это глупый ответ. Цель «экспорта» состоит в том, чтобы заставить переменные «находиться в среде последующих выполняемых команд», являются ли эти команды субхолмами или подпроцессами. Наивная реализация заключалась бы в том, чтобы просто поместить переменную в среду оболочки, но это сделало бы невозможным реализовать export -p.

63
ответ дан William Pursell 18 August 2018 в 06:36
поделиться
  • 1
    Обратите внимание, что это не совсем так. В bash экспорт действительно добавляет переменную в среду текущей оболочки, но это не относится к dash. Мне кажется, что добавление переменной в среду текущей оболочки является самым простым способом реализации семантики export, но это поведение не является обязательным. – William Pursell 2 July 2013 в 14:09
  • 2
    Я не уверен, что dash имеет к этому отношение. Оригинальный плакат задавал конкретно о bash. – Starfish 7 September 2013 в 05:17
  • 3
    Вопрос отмечен bash, но в равной степени относится к любому варианту bourne-shell. Быть чрезмерно конкретным и давать ответы, которые применяются только к bash, - это великое зло. – William Pursell 7 September 2013 в 08:17
  • 4
    bash - это jQuery оболочки. – Potherca 24 May 2014 в 18:10
  • 5
    export makes the variable available to subshells, and that is correct Это очень запутанное использование терминологии. Подледы не нуждаются в export для наследования переменных. Подпроцессы. – Amit Naidu 19 May 2018 в 18:37
Другие вопросы по тегам:

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