Как экспортировать переменные из файла?

Вопрос или проблема

У меня есть файл tmp.txt, содержащий переменные для экспорта, например:

a=123
b="hello world"
c="one more variable"

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

set -a
. ./tmp.txt
set +a

set -a заставляет переменные¹, определенные с этого момента, автоматически экспортироваться. Это доступно в любой оболочке, подобной Bourne. . является стандартным и Bourne-именем для команды source, поэтому я предпочитаю его для портативности (source происходит из csh и теперь доступен в большинстве современных оболочек, подобных Bourne, включая bash, хотя иногда с немного другим поведением).

В оболочках POSIX вы также можете использовать

set -o allexport
. ./tmp.txt
set +o allexport

как более описательное альтернативное решение.

Вы можете сделать это функцией с:

export_from() {
  local _export_from_ret _export_from_restore _export_from_file

  _export_from_ret=0

  case $- in
    (*a*) _export_from_restore=;;
    (*)   _export_from_restore="set +a";;
  esac

  for _export_from_file do
    command . "$_export_from_file" || _export_from_ret="$?"
  done
  eval "$_export_from_restore"
  return "$_export_from_ret"
}

¹ В bash имейте в виду, что это также приводит к тому, что все функции, объявленные во время включения allexport, будут экспортированы в окружение (как BASH_FUNC_myfunction%% переменные окружения, которые затем импортируются всеми оболочками bash, запущенными в этом окружении, даже при запуске как sh).

source tmp.txt
export a b c
./child ...

Судя по вашему другому вопросу, вы не хотите жестко кодировать имена переменных:

source tmp.txt
export $(cut -d= -f1 tmp.txt)

проверьте это:

$ source tmp.txt
$ echo "$a $b $c"
123 hello world one more variable
$ perl -E 'say "@ENV{qw(a b c)}"'

$ export $(cut -d= -f1 tmp.txt)
$ perl -E 'say "@ENV{qw(a b c)}"'
123 hello world one more variable

Опасный однострочник, который не требует source:

export $(xargs <file)
  • Он не может обрабатывать комментарии, часто используемые в файлах окружения
  • Он не может обрабатывать значения с пробелами, как в примере вопроса
  • Он может непреднамеренно расширить шаблоны glob в файлы, если они каким-то образом совпадут

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

Просто сделайте:

while read LINE; do export "$LINE"; done < ./tmp.txt

Просто дополняя отличный ответ @Stéphane Chazelas, вы также можете использовать set -a/set +a и его эквиваленты внутри файла (например, “to_export.bash”) вот так…

set -a    
SOMEVAR_A="abcd"
SOMEVAR_B="efgh"
SOMEVAR_C=123456
set +a

… а затем экспортировать все переменные, содержащиеся в файле, вот так…

. ./to_export.bash

… или…

source ./to_export.bash

Спасибо! 🤗

Я собрал решение, которое, похоже, работает во всех случаях (пробелы, комментарии и т. д.), используя различные предложенные решения. Вот оно:

eval $(egrep "^[^#;]" .env | xargs -d'\n' -n1 | sed 's/^/export /')

Вам не нужно запускать export на содержимом строки, вы просто используете его, чтобы отметить символы, которые вы хотите экспортировать. Я использую эту функцию:

sourcery () {
    local file vars
    for file; do
            source "$file" && {
                    mapfile -t vars < <(sed -nE '/^[[:space:]]*#/d;s/^[[:space:]]*([[:alpha:]_][[:alnum:]_]*)=.*/\1/p' "$file")
                    export "${vars[@]}"
            }
    done
}

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

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

Моя версия предполагает bash и sed, поддерживающий -E, но вы можете написать высокопортативную версию той же идеи без особых проблем.

Это решение экспортирует все key=values в переменные окружения, которые находятся в файле .env, которые не являются пустыми строками или закомментированными (#).

Файл: .env

ENV=local
DEBUG=True

Команда:

$ export $(cat .env | egrep -v "(^#.*|^$)" | xargs)

Мой взгляд:

dotenv() {
    local REPLY
    while read; do
        REPLY=$(printf %s\\n "${REPLY%%#*}" | xargs)
        [[ -n $REPLY ]] && export "$REPLY"
    done < <(envsubst)
}

Поддерживает комментарии, обрабатывает пробелы, кавычки и символы обратной косой черты (обработка xargs), и расширяет переменные окружения. Избегает произвольного выполнения скриптов из source.

Без xargs и envsubst синтаксис немного изменяется (без расшифровки или общей пост-обработки), но комментарии все равно поддерживаются и функция является только bash.

Ее можно дополнительно улучшить, чтобы предоставить более приятные сообщения об ошибках в плохих строках.

Для моего случая использования,

export $(< ~/my/.env)

работает так, как задумано.

Небольшое решение, основанное на одном из ответов:

  1. создайте функцию и поместите ее в ~/.bashrc
function myenvs() {

    if [ -z "$1" ]; then
        echo "Использование: myenvs [путь к файлу импорта]";
    else
        if [ -f "$1" ]; then
            source "$1" 2>/dev/null; export $(cat "$1" | grep "=" | grep -v "^#" | awk /./ | cut -d= -f1 | xargs)
        else
            echo "Неверный путь к файлу: $1"
        fi
    fi
}
  1. запустите $ myenvs /path/to/env/file, чтобы импортировать envs

※ если env/file содержит плохие строки, здесь могут появиться ошибки, когда вызывается source. Я просто прячу их, так что обработка ошибок в ваших руках

Это надежно к таким вещам, как завершающие комментарии и ведущие пробелы…

while read -r i ; do eval "export ${i}" ; done <<<$(grep -vxE '[[:blank:]]*([#;].*)?' "my.vars")

Проверено с ниже приведенным “my.vars”…

   ## некоторые переменные
   var1="ABCD" ## комментарий
   var2="abc#def"
   var3="hello world"

При желании вы можете добавить префикс к именам (например, с Terraform TF_VAR), заменив…

eval "export PREFIX_${i}"

Ссылки:

Ответ или решение

Как экспортировать переменные из файла в Linux

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

1. Директивы set -a и set +a

Одним из наиболее простых и надежных способов экспорта переменных является использование команды set -a. Эта команда заставляет оболочку автоматически экспортировать все переменные, которые будут объявлены после нее.

set -a  # Включаем автоматический экспорт
. ./tmp.txt  # Считываем файл, содержащий переменные
set +a  # Отключаем автоматический экспорт

2. Использование команды source

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

source ./tmp.txt
export a b c  # Экспортируем переменные

3. Экспорт переменных без жесткого кодирования имен

Если вы хотите избежать необходимости жестко кодировать имена переменных, можно использовать следующий подход:

source ./tmp.txt
export $(cut -d= -f1 tmp.txt)  # Экспортируем только имена переменных

Этот метод извлекает имена переменных из файла и экспортирует их в окружение.

4. Построчное чтение и экспорт переменных

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

while read -r LINE; do
    export "$LINE"
done < ./tmp.txt

5. Использование eval для поддержки сложных строк

Сложные конструкции можно обработать с помощью eval. С помощью регулярных выражений вы можете отфильтровать строки, игнорируя комментарии и пустые строки.

eval $(egrep "^[^#;]" ./tmp.txt | xargs -d'\n' -n1 | sed 's/^/export /')

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

6. Функция для экспорта переменных

Для улучшения удобства можно создать функцию, которую можно сохранить в вашем файле конфигурации ~/.bashrc:

function myenvs() {
    if [ -z "$1" ]; then
        echo "Usage: myenvs [import file path]"
    else
        if [ -f "$1" ]; then
            source "$1" 2>/dev/null
            export $(awk -F= '/^[^#]/{print $1}' "$1" | xargs)
        else
            echo "Bad file path: $1"
        fi
    fi
}

7. Безопасный и универсальный подход

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

while IFS= read -r line; do
    [[ $line =~ ^[[:blank:]]*#.*$ ]] && continue  # Пропускаем комментарии
    [[ -z $line ]] && continue  # Пропускаем пустые строки
    export "$line"
done < ./tmp.txt

Это обеспечит, что ни одна важная информация не будет потеряна или искажена.

Заключение

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

Оцените материал
Добавить комментарий

Капча загружается...