- Вопрос или проблема
- Ответ или решение
- Как экспортировать переменные из файла в Linux
- 1. Директивы set -a и set +a
- 2. Использование команды source
- 3. Экспорт переменных без жесткого кодирования имен
- 4. Построчное чтение и экспорт переменных
- 5. Использование eval для поддержки сложных строк
- 6. Функция для экспорта переменных
- 7. Безопасный и универсальный подход
- Заключение
Вопрос или проблема
У меня есть файл 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)
работает так, как задумано.
Небольшое решение, основанное на одном из ответов:
- создайте функцию и поместите ее в
~/.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
}
- запустите
$ 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
Это обеспечит, что ни одна важная информация не будет потеряна или искажена.
Заключение
Экспорт переменных окружения из файла является критически важным навыком, особенно для системных администраторов, разработчиков и инженерных команд. Приведенные выше методы позволяют гибко и безопасно управлять переменными окружения, учитывая различные сценарии использования, и настраивать окружение для успешной работы приложений. Выбирайте метод, который соответствует вашим потребностям наилучшим образом, и всегда учитывайте безопасность и управляемость при выполнении операций с окружением.