Задать переменные среды из файла

Я пишу скрипт в bash, который анализирует файлы с 3 переменными в определенной папке, это один из них:

MINIENTREGA_FECHALIMITE="2011-03-31"
MINIENTREGA_FICHEROS="informe.txt programa.c"
MINIENTREGA_DESTINO="./destino/entrega-prac1"

этот файл хранится в ./ conf / prac1

мой скрипт minientrega.sh затем анализирует файл с помощью этого кода:

cat ./conf/ | while read line; do
    export $line
done

но когда я выполнить minientrega.sh prac1 в командной строке он не устанавливает переменные среды

Я также попытался с помощью source ./conf/ но та же проблема по-прежнему применяется

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

19 ответов


проблема с вашим подходом является export на while цикл происходит в суб-оболочке, и эта переменная не будет доступна в текущей оболочке (родительская оболочка цикла while).

добавить в самом файле:

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 материал в моей консоли rails.

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/(.*)=.*//' | 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
...

на 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
}

eval $(cat .env | sed 's/^/export /')

вот еще sed решение, которое не запускает eval или не требует ruby:

source <(sed -E -n 's/[^#]+/export &/ p' ~/.env)

это добавляет экспорт, сохраняя комментарии к строкам, начинающимся с комментария.

.env contents

A=1
#B=2

образца

$ sed -E -n 's/[^#]+/export &/ p' ~/.env
export A=1
#export B=2

я нашел это особенно полезно при создании такого файла для загрузки в файл блока systemd, с EnvironmentFile.


SAVE=$(set +o) && set -o allexport && . .env; eval "$SAVE"

Это позволит сохранить/восстановить исходные параметры, какими бы они ни были.

используя set -o allexport имеет преимущество правильного пропуска комментариев без регулярного выражения.

set +o сам по себе выводит все ваши текущие параметры в формате, который bash может позже выполнить. Также удобно:set -o сам по себе, выводит все ваши текущие параметры в удобном для человека формате.


Я ввел ответ user4040650, потому что он прост, и он позволяет комментарии в файле (т. е. строки, начинающиеся с#), что очень желательно для меня, так как комментарии, объясняющие переменные, могут быть добавлены. Просто переписываю в контексте первоначального вопроса.

Если скрипт callled как указано: minientrega.sh prac1, тогда minientrega.sh мог бы:

set -a # export all variables created next
source 
set +a # stop exporting

# test that it works
echo "Ficheros: $MINIENTREGA_FICHEROS"

следующее было извлечено из набор документации:

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

set [--abefhkmnptuvxBCEHPT] [- o option-name] [аргумент ...] set [+abefhkmnptuvxBCEHPT] [+o option-name] [аргумент ...]

Если параметры или аргументы не указаны, set отображает имена и значения всех оболочек переменные и функции, отсортированный по текущей локали, в формат, который может быть использован в качестве входного для установки или сброса в настоящее время-набор переменных. Переменные только для чтения не могут быть сброшены. В POSIX mode, перечислены только переменные оболочки.

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

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

а также:

использование ‘ + 'вместо' - ' приводит к отключению этих параметров. Этот опции также могут использоваться при вызове оболочки. Текущий набор из вариантов можно найти в$ -.


улучшение ответа Сайласа Павла

экспорт переменных в подрешетке делает их локальными для команды.

(export $(cat .env | xargs) && rails c)


проще:

  1. захватить содержимое файла
  2. удалите все пустые строки (просто incase вы отделили некоторые вещи)
  3. удалить любые комментарии (просто incase вы добавили некоторые...)
  4. добавить export ко всем строкам
  5. 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 | 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

основываясь на других ответах, вот способ экспортировать только подмножество строк в файл, включая значения с пробелами, такими как PREFIX_ONE="a word":

set -a
. <(grep '^[ ]*PREFIX_' conf-file)
set +a

у меня есть проблемы с ранее предложенными решениями:

  • решение@anubhava делает написание файлов конфигурации bash friendly очень раздражающим очень быстро, а также - вы можете не всегда экспортировать свою конфигурацию.
  • @Silas Paul решение ломается, когда у вас есть переменные, которые имеют пробелы или другие символы, которые хорошо работают в кавычках значений, но $() делает беспорядок.

вот мое решение, которое все еще довольно ужасно IMO-и не решает проблему "экспорт только в один ребенок", рассмотренную Сайласом (хотя вы, вероятно, можете запустить ее в под-оболочке, чтобы ограничить область):

source .conf-file
export $(cut -d= -f1 < .conf-file)

пробелы в значении

здесь есть много отличных ответов, но я нашел, что им всем не хватает поддержки белого пространства в значении:

DATABASE_CLIENT_HOST=host db-name db-user 0.0.0.0/0 md5

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

один на основе sed и @javier-buzzi ответ:

source <(sed -e /^$/d -e /^#/d -e 's/.*/declare -x "&"/g' .env)

и один с прочитанной строкой в цикле на основе @john1024 ответ

while read -r line; do declare -x "$line"; done < <(egrep -v "(^#|^\s|^$)" .env)

ключ заключается в использовании declare -x и ввод строки в двойные кавычки. Я не знаю, почему, но когда вы переформатируете код цикла на несколько строк, он не будет работать - я не программист bash, я просто сожрал их, это все еще магия для меня:)


если вы получаете ошибку, потому что одна из ваших переменных содержит значение, содержащее пробелы, вы можете попытаться сбросить bash IFS (внутренний разделитель полей) в \n пусть Баш интерпретирует cat .env результат в виде списка параметров для env исполняемый файл.

пример:

IFS=$'\n'; env $(cat .env) rails c

посмотреть также:


Если вы хотите загрузить ваш .env-файл в запущенный процесс внутри кода Visual Studio можно добавить ссылку на свой .env файл в вашем launch.json С помощью envFile свойства:

"configurations": [
    {
        "name": "Launch server.js with .env",
        "type": "node",
        "request": "launch",
        "envFile": "${workspaceRoot}/.env",
        ...
    }
]

я наткнулся на эту тему, когда пытался повторно использовать Docker --env-files в оболочке. формат не совместим с bash, но это просто:name=value, не цитирую, нет замены. Они также игнорируют пустые строки и # комментарии.

Я не мог получить совместимость с posix, но вот тот, который должен работать в bash-подобных оболочках (протестирован в zsh на OSX 10.12.5 и bash на Ubuntu 14.04):

while read -r l; do export "$(sed 's/=.*$//' <<<$l)"="$(sed -E 's/^[^=]+=//' <<<$l)"; done < <(grep -E -v '^\s*(#|$)' your-env-file)

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

  • bash: export: `123qwe=bar': not a valid identifier
  • bash: export: `org.spring.config=something': not a valid identifier
  • и он не будет обрабатывать синтаксис passthrough (голый FOO)

мой .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