Установить переменные окружения из файла значений ключа / пары
TL;DR: как экспортировать набор пар ключ / значение из текстового файла в среду оболочки?
Для справки ниже приведена оригинальная версия вопроса с примерами.
Я пишу скрипт на bash, который анализирует файлы с 3 переменными в определенной папке, это одна из них:
MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"
Этот файл хранится в./conf/prac1
Мой скрипт minientrega.sh затем анализирует файл, используя этот код:
cat ./conf/$1 | while read line; do
export $line
done
Но когда я выполню minientrega.sh prac1
в командной строке не устанавливает переменные окружения
Я также пытался использовать source ./conf/$1
но та же проблема все еще применяется
Возможно, есть какой-то другой способ сделать это, мне просто нужно использовать переменные окружения файла, который я передаю в качестве аргумента моего скрипта.
52 ответа
Проблема с вашим подходом export
в while
Цикл происходит во вспомогательной оболочке, и эти переменные не будут доступны в текущей оболочке (родительская оболочка цикла while).
добавлять export
Команда в самом файле:
export MINIENTREGA_FECHALIMITE="2011-03-31"
export MINIENTREGA_FICHEROS="informe.txt programa.c"
export MINIENTREGA_DESTINO="./destino/entrega-prac1"
Затем вам нужно получить исходный код в файле в текущей оболочке, используя:
. ./conf/prac1
ИЛИ ЖЕ
source ./conf/prac1
Это может быть полезно:
export $(cat .env | xargs) && rails c
Причина, почему я использую это, если я хочу проверить .env
вещи в моей консоли рельсов.
gabrielf хороший способ сохранить переменные локальными. Это решает потенциальную проблему при переходе от проекта к проекту.
env $(cat .env | xargs) rails
Я проверил это с bash 3.2.51(1)-release
Обновить:
Игнорировать строки, начинающиеся с #
, используйте это (благодаря комментарию Пита):
export $(grep -v '^#' .env | xargs)
И если вы хотите unset
все переменные, определенные в файле, используйте это:
unset $(grep -v '^#' .env | sed -E 's/(.*)=.*/\1/' | xargs)
Обновить:
Чтобы также обрабатывать значения с пробелами, используйте:
export $(grep -v '^#' .env | xargs -d '\n')
в системах GNU или:
export $(grep -v '^#' .env | xargs -0)
на системах BSD.
-o allexport
позволяет экспортировать все следующие определения переменных. +o allexport
отключает эту функцию.
set -o allexport
source conf-file
set +o allexport
set -a
. ./env.txt
set +a
Если env.txt
как:
VAR1=1
VAR2=2
VAR3=3
...
Я нашел самый эффективный способ:
export $(xargs < .env)
Объяснение
Когда у нас есть .env
файл вроде этого:
key=val
foo=bar
пробег xargs < .env
получите key=val foo=bar
так что мы получим export key=val foo=bar
и это именно то, что нам нужно!
Ограничение
- Он не обрабатывает случаи, когда значения содержат пробелы. Такие команды, как env, создают этот формат. - @Shardj
allexport
опция упоминается в нескольких других ответах здесь, для которых set -a
это ярлык. Поиск.env действительно лучше, чем циклический переход по строкам и экспорт, потому что он допускает комментарии, пустые строки и даже переменные окружения, сгенерированные командами. Мой.bashrc включает в себя следующее:
# .env loading in the shell
dotenv () {
set -a
[ -f .env ] && . .env
set +a
}
# Run dotenv on login
dotenv
# Run dotenv on every new directory
cd () {
builtin cd $@
dotenv
}
Проблема в том, что он требует, чтобы файл имел правильный синтаксис bash, а некоторые специальные символы испортят его:
=
,
"
,
'
,
<
,
>
, и другие. Поэтому в некоторых случаях вы не можете просто
source development.env
Однако эта версия поддерживает все специальные символы в значениях:
set -a
source <(cat development.env | \
sed -e '/^#/d;/^\s*$/d' -e "s/'/'\\\''/g" -e "s/=\(.*\)/='\1'/g")
set +a
Объяснение:
-
-a
означает, что каждая переменная bash станет переменной среды -
/^#/d
удаляет комментарии (строки, начинающиеся с#
) -
/^\s*$/d
удаляет пустые строки, включая пробелы -
"s/'/'\\\''/g"
заменяет каждую цитату на'\''
, который в bash представляет собой трюк для создания цитаты :) -
"s/=\(.*\)/='\1'/g"
конвертирует каждыйa=b
вa='b'
В результате вы можете использовать специальные символы :)
Чтобы отладить этот код, замените
source
с
cat
и вы увидите, что производит эта команда.
Вот еще один sed
решение, которое не запускает eval или не требует ruby:
source <(sed -E -n 's/[^#]+/export &/ p' ~/.env)
Это добавляет экспорт, сохраняя комментарии в строках, начиная с комментария.
содержание.env
A=1
#B=2
пробный прогон
$ sed -E -n 's/[^#]+/export &/ p' ~/.env
export A=1
#export B=2
Я нашел это особенно полезным при создании такого файла для загрузки в файл системного модуля, сEnvironmentFile
,
Не совсем уверен, почему или что я пропустил, но после того, как я прочитал большинство ответов и потерпел неудачу. Я понял, что с этим файлом.env:
MY_VAR="hello there!"
MY_OTHER_VAR=123
Я мог бы просто сделать это:
source .env
echo $MY_VAR
Выходы: Hello there!
Кажется, отлично работает в Ubuntu linux.
Самый короткий путь, который я нашел:
Ваш .env
файл:
VARIABLE_NAME="A_VALUE"
Тогда просто
. ./.env && echo ${VARIABLE_NAME}
Бонус: потому что это короткий однострочник, это очень полезно в package.json
файл
"scripts": {
"echo:variable": ". ./.env && echo ${VARIABLE_NAME}"
}
Я проголосовал за ответ user4040650, потому что он простой и допускает комментарии в файле (т.е. строки, начинающиеся с #), что для меня крайне желательно, так как комментарии, объясняющие переменные, могут быть добавлены. Просто переписываю в контексте оригинального вопроса.
Если скрипт называется как указано: minientrega.sh prac1
, тогда minientrega.sh может иметь:
set -a # export all variables created next
source $1
set +a # stop exporting
# test that it works
echo "Ficheros: $MINIENTREGA_FICHEROS"
Следующее было извлечено из комплекта документации:
Эта встроенная программа настолько сложна, что заслуживает отдельного раздела. set позволяет изменять значения параметров оболочки и задавать позиционные параметры или отображать имена и значения переменных оболочки.
set [--abefhkmnptuvxBCEHPT] [-o имя-опции] [аргумент…] set [+abefhkmnptuvxBCEHPT] [+o-имя-опции] [аргумент…]
Если параметры или аргументы не предоставлены, set отображает имена и значения всех переменных и функций оболочки, отсортированных в соответствии с текущей локалью, в формате, который можно использовать повторно в качестве входных данных для установки или сброса текущих установленных переменных. Переменные только для чтения не могут быть сброшены. В режиме POSIX перечислены только переменные оболочки.
Когда параметры предоставляются, они устанавливают или отменяют атрибуты оболочки. Опции, если указаны, имеют следующие значения:
-a Каждая переменная или функция, которая создается или изменяется, получает атрибут экспорта и помечается для экспорта в среду последующих команд.
И это также:
Использование "+" вместо "-" приводит к отключению этих параметров. Опции также могут использоваться при вызове оболочки. Текущий набор параметров можно найти в $-.
SAVE=$(set +o) && set -o allexport && . .env; eval "$SAVE"
Это сохранит / восстановит ваши исходные параметры, какими бы они ни были.
С помощью set -o allexport
имеет преимущество правильного пропуска комментариев без регулярных выражений.
set +o
Сам по себе выводит все ваши текущие параметры в формате, который впоследствии может выполнить bash. Также удобно: set -o
сам выводит все ваши текущие параметры в удобном для человека формате.
Улучшение ответа Сайласа Павла
экспорт переменных в подоболочку делает их локальными для команды.
(export $(cat .env | xargs) && rails c)
Вот мой вариант:
with_env() {
(set -a && . ./.env && "$@")
}
по сравнению с предыдущими решениями:
- он не пропускает переменные за пределы области видимости (значения из
.env
не выставляются на звонилку) - не трепится
set
параметры - возвращает код выхода выполненной команды
- использует posix-совместимый
set -a
- использует
.
вместо тогоsource
избегать башизма - команда не вызывается, если
.env
загрузка не удалась
with_env rails console
Если
env
поддерживает
-S
вариант можно использовать символы новой строки или escape-символы, такие как
\n
или же
\t
(см. env):
env -S "$(cat .env)" command
.env
пример файла:
KEY="value with space\nnewline\ttab\tand
multiple
lines"
Тест:
env -S "$(cat .env)" sh -c 'echo "$KEY"'
Используйте shdotenv
Поддержка dotenv для оболочки и POSIX-совместимой спецификации синтаксиса .env
https://github.com/ko1nksm/shdotenv
eval "$(shdotenv)"
Применение
Usage: shdotenv [OPTION]... [--] [COMMAND [ARG]...]
-d, --dialect DIALECT Specify the .env dialect [default: posix]
(posix, ruby, node, python, php, go, rust, docker)
-s, --shell SHELL Output in the specified shell format [default: posix]
(posix, fish)
-e, --env ENV_PATH Location of the .env file [default: .env]
Multiple -e options are allowed
-o, --overload Overload predefined environment variables
-n, --noexport Do not export keys without export prefix
-g, --grep PATTERN Output only those that match the regexp pattern
-k, --keyonly Output only variable names
-q, --quiet Suppress all output
-v, --version Show the version and exit
-h, --help Show this message and exit
Требования
shdotenv - это сценарий оболочки для одного файла со встроенным сценарием awk.
- Оболочка POSIX (тире, bash, ksh, zsh и т. Д.)
- awk (gawk, nawk, mawk, busybox awk)
Извините, что добавляю еще один ответ, но поскольку он упрощен и работает во многих случаях, попробуйте:
export $(< ~/my/.env)
Simpler:
- захватить содержимое файла
- удалите все пустые строки (только если вы отделили некоторые вещи)
- удалить любые комментарии (только если вы добавили некоторые...)
- добавлять
export
на все линии eval
Все это
eval $(cat .env | sed -e /^$/d -e /^#/d -e 's/^/export /')
Другой вариант (вам не нужно бежать eval
(спасибо @Jaydeep)):
export $(cat .env | sed -e /^$/d -e /^#/d | xargs)
Наконец, если вы хотите сделать свою жизнь ДЕЙСТВИТЕЛЬНО легкой, добавьте это к ~/.bash_profile
:
function source_envfile() { export $(cat $1 | sed -e /^$/d -e /^#/d | xargs); }
(УБЕДИТЕСЬ, ЧТО ВЫ ПЕРЕГРУЖАЕТЕ НАСТРОЙКИ BASH!!! source ~/.bash_profile
или.. просто создайте новую вкладку / окно и проблема решена) вы называете это так: source_envfile .env
Вы можете использовать свой оригинальный скрипт для установки переменных, но вам нужно вызвать его следующим образом (с отдельной точкой):
. ./minientrega.sh
Также может быть проблема с cat | while read
подход. Я бы порекомендовал использовать подход while read line; do .... done < $FILE
,
Вот рабочий пример:
> cat test.conf
VARIABLE_TMP1=some_value
> cat run_test.sh
#/bin/bash
while read line; do export "$line";
done < test.conf
echo "done"
> . ./run_test.sh
done
> echo $VARIABLE_TMP1
some_value
Я работаю с docker-compose и .env
файлы на Mac, и хотел импортировать .env
в мою оболочку bash (для тестирования), и "лучшим" ответом здесь было срабатывание следующей переменной:
.env
NODE_ARGS=--expose-gc --max_old_space_size=2048
Решение
Так что я в конечном итоге с помощью eval
и завернуть мои env var def в одинарные кавычки.
eval $(grep -v -e '^#' .env | xargs -I {} echo export \'{}\')
Версия Bash
$ /bin/bash --version
GNU bash, version 3.2.57(1)-release (x86_64-apple-darwin18)
Copyright (C) 2007 Free Software Foundation, Inc.
t=$(mktemp) && export -p > "$t" && set -a && . ./.env && set +a && . "$t" && rm "$t" && unset t
Как это устроено
- Создать временный файл.
- Записать все текущие значения переменных среды во временный файл.
- Разрешить экспорт всех объявленных переменных в исходном скрипте в среду.
- Читать
.env
файл. Все переменные будут экспортированы в текущую среду. - Отключите экспорт всех объявленных переменных в исходном скрипте в среду.
- Прочтите содержимое временного файла. Каждая строка будет иметь
declare -x VAR="val"
который экспортирует каждую из переменных в среду. - Удалить временный файл.
- Отключите переменную, содержащую имя временного файла.
особенности
- Сохраняет значения переменных, уже установленных в среде
.env
могут быть комментарии.env
могут быть пустые строки.env
не требует специального верхнего или нижнего колонтитула, как в других ответах (set -a
а такжеset +a
).env
не требует наличияexport
для каждого значения- один лайнер
Мои требования были:
- простой.env файл без
export
префиксы (для совместимости с дотенв) - вспомогательные значения в кавычках: TEXT="альфа браво чарли"
- поддерживающие комментарии с префиксом # и пустыми строками
- универсальный для Mac/BSD и Linux/GNU
Полная рабочая версия составлена из ответов выше:
set -o allexport
eval $(grep -v '^#' .env | sed 's/^/export /')
set +o allexport
Основываясь на других ответах, вот способ экспортировать только подмножество строк в файле, включая значения с такими пробелами, как PREFIX_ONE="a word"
:
set -a
. <(grep '^[ ]*PREFIX_' conf-file)
set +a
У меня есть проблемы с ранее предложенными решениями:
- Решение @anubhava делает очень удобной запись файлов конфигурации, удобных для bash, а также - вы можете не захотеть всегда экспортировать свою конфигурацию.
- Решение @Silas Paul ломается, когда у вас есть переменные с пробелами или другими символами, которые хорошо работают в кавычках, но
$()
делает беспорядок из.
Вот мое решение, которое все еще довольно ужасно для ИМО - и не решает проблему "экспорта только одному дочернему элементу", решаемую Сайласом (хотя вы, вероятно, можете запустить ее в под-оболочке, чтобы ограничить область действия):
source .conf-file
export $(cut -d= -f1 < .conf-file)
Мой.env:
#!/bin/bash
set -a # export all variables
#comments as usual, this is a bash script
USER=foo
PASS=bar
set +a #stop exporting variables
Вызов:
source .env; echo $USER; echo $PASS
Ссылка https://unix.stackexchange.com/questions/79068/how-to-export-variables-that-are-set-all-at-once
Вот мой взгляд на это. У меня были следующие требования:
- Игнорировать прокомментированные строки
- Разрешить пробелы в значении
- Разрешить пустые строки
- Возможность передать пользовательский файл env при использовании по умолчанию.env
- Разрешить экспорт, а также запуск команд в строке
- Выйти, если файл env не существует
source_env() {
[ "$#" -eq 1 ] && env="$1" || env=".env"
[ -f "$env" ] || { echo "Env file $env doesn't exist"; return 1; }
eval $(grep -Ev '^#|^$' "$env" | sed -e 's/=\(.*\)/="\1/g' -e 's/$/"/g' -e 's/^/export /')
}
Использование после сохранения функции в вашем.bash_profile или аналогичном:
source_env # load default .env file
source_env .env.dev # load custom .env file
(source_env && COMMAND) # run command without saving vars to environment
На основе Хавьера и некоторых других комментариев.
Моя версия:
Я распечатываю файл, удаляю закомментированные строки, пустые строки и разделяю ключ / значение со знаком «=». Затем я просто применяю команду экспорта.
Преимущество этого решения заключается в том, что файл может содержать специальные символы в значениях, такие как каналы, теги html и т. Д., И значение не нужно заключать в кавычки, как файл реальных свойств.
# Single line version
cat myenvfile.properties | grep -v '^#' | grep '=' | while read line; do IFS=\= read k v <<< $line; export $k="$v"; done
# Mutliline version:
cat myenvfile.properties | grep -v '^#' | grep '=' | while read line; do
IFS=\= read k v <<< $line
export $k="$v"
done
Некоторые примечания:
- Файл «.env» должен иметь последовательность конца строки «LF».
- Избегайте использования динамических значений в переменных среды, таких как
variable1=$variable2@$variable3
- Избегайте использования цитат (
"
) в переменных среды vavlue, напримерvariable="value"
Это лучший и самый короткий ответ
source .env && export $(cut -d= -f1 < .env)
Изменено из @Dan Kowalczyk
Я положил это в ~/.bashrc
.
set -a
. ./.env >/dev/null 2>&1
set +a
Кросс-совместимый очень хорошо с плагином dotenv Oh-my-Zsh. (Есть Oh-my-bash, но у него нет плагина dotenv.)