Установка переменной окружения в той же строке, что и выполнение программы, отличается от установки отдельно? - переменные оболочки и переменные среды

В чем разница между:

prompt$   TSAN_OPTIONS="suppressions=/somewhere/file" ./myprogram

а также

prompt$   TSAN_OPTIONS="suppressions=/somewhere/file"
prompt$   ./myprogram

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

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

Какая разница?

Бонусный вопрос: как первый случай даже запускается без ошибок? Не должно быть; или && между ними? Ответ на этот вопрос, вероятно, ответит на мою первую...

Ответ 1

Команда VAR=value command формата устанавливает переменную VAR для значения value в среде команды command. Раздел spec, описывающий это, - это простые команды. В частности:

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

Формат VAR=value; command VAR=value; command устанавливает переменную оболочки VAR в текущую оболочку, а затем запускает command как дочерний процесс. Детский процесс ничего не знает о переменных, заданных в процессе оболочки.

Механизм, с помощью которого процесс экспортирует (подсказка подсказки) переменную, которую должны видеть дочерние процессы, - это установить их в своей среде перед запуском дочернего процесса. Встроенная оболочка, которая делает это export. Вот почему вы часто видите export VAR=value и export VAR=value VAR=value; export VAR VAR=value; export VAR.

Синтаксис, который вы обсуждаете, является короткой формой для чего-то похожего:

VAR=value
export VAR
command
unset -v VAR

только без использования текущей рабочей среды.

Ответ 2

В дополнение к полезному ответу Этана Рейснера:

Важно различать переменные оболочки и переменные среды:

Примечание. Следующее относится ко всем POSIX-совместимым оболочкам;Расширения bash -specific отмечены как таковые.

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

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

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

Таким образом,

  • любые переменные, которые вы создаете неявно путем назначения - например, TSAN_OPTIONS="suppressions=/somewhere/file" - являются ТОЛЬКО переменными оболочки, но НЕ ТАКЖЕ переменными окружения,
  • ЗА ИСКЛЮЧЕНИЕМ - возможно, смутно - при добавлении непосредственно к команде - например, TSAN_OPTIONS="suppressions=/somewhere/file"./myprogram - в этом случае они являются ТОЛЬКО переменными окружения, действующими только для THAT COMMAND.
    • Вот что описывает этот ответ.

Переменные оболочки также являются переменными среды при следующих обстоятельствах:

  • основанные на переменных среды, которые сама оболочка унаследовала, например $HOME
  • переменные оболочки, созданные явно с помощью export varName[=value] или, в bash, также с declare -x varName[=value]
    • напротив, в bash, используя declare без -x или используя local в функции, создает простые переменные оболочки
  • переменные оболочки, созданные неявно, в то время как опция оболочки -a действует (с ограниченными исключениями)

Когда переменная оболочки помечена как экспортированная - то есть, помечена как переменная среды - любые последующие изменения в переменной оболочки также обновляют переменную среды; например:

export TSAN_OPTIONS  # creates shell variable *and* corresponding environment variable

# ...

TSAN_OPTIONS="suppressions=/somewhere/file" # updates *both* the shell and env. var.

  • export -p печатает все переменные среды
  • unset [-v] MYVAR undefines shell variable $MYVAR а также удаляет его как переменную среды, если это применимо.
  • в bash:
    • Вы можете "исключить" заданную переменную, не отменяя ее как переменную оболочки с export -n MYVAR - это удаляет MYVAR из среды, но сохраняет текущее значение в качестве переменной оболочки.
    • declare -p MYVAR печатает переменную $MYVAR текущее значение вместе со своими атрибутами; если выход начинается с declare -x, экспортируется $MYVAR (является переменной среды)