如何从Makefile中的.env文件加载和导出变量?

Bas*_*hur 7 makefile environment-variables

.env在Makefile中使用a的最佳方法是什么,即加载该文件并导出子shell中的所有变量make

如果提议的解决方案make仅适用于例如不使用任何第三方工具,那将是很好的.此外,.env文件支持多行变量,例如:

FOO="this\nis\na\nmultiline\nvar"

这就是为什么这个解决方案可能不够的原因.

ede*_*bin 20

发现了这个并且效果很好:

在 makefile 的顶部

ifneq (,$(wildcard ./.env))
    include .env
    export
endif
Run Code Online (Sandbox Code Playgroud)

然后你为所有环境创建变量,例如 MY_VAR 用作 $(MY_VAR)

  • 这可行,但我必须做一些谷歌搜索才能了解如何...所以对于其他人来说... `ifneq` + `wildcard` 是检查文件是否存在的典型方法;`include .env` 将 `.env` 导入 makefile 变量,不带参数的 `export` 导出所有变量 (3认同)

Art*_*rFH 14

Make 不提供将文件内容读取到某个变量的任何方法。所以,我认为不使用外部工具是不可能达到这个结果的。但是,如果我错了,我很乐意学习一些新技巧。

因此,让我们假设有两个文件.env, 是技术上正确的 shell 文件:

FOO=bar

BAR="notfoo" # comment
   #comment
MULTILINE="This\nis\nSparta!"
# comment
Run Code Online (Sandbox Code Playgroud)

script.sh

#!/bin/bash
echo FOO=${FOO}
echo BAR=${BAR}
echo -e ${MULTILINE}
Run Code Online (Sandbox Code Playgroud)

一种解决方案是包含.env文件,然后确保导出变量:

include .env

$(eval export $(shell sed -ne 's/ *#.*$//; /./ s/=.*$$// p' .env))

all:
    ./script.sh
Run Code Online (Sandbox Code Playgroud)

由于 shell 和 make 对引号的处理不同,您将在输出中看到引号。

您可以通过 make 重新处理变量来避免这种情况:

include .env

VARS:=$(shell sed -ne 's/ *\#.*$$//; /./ s/=.*$$// p' .env )
$(foreach v,$(VARS),$(eval $(shell echo export $(v)="$($(v))")))

all:
    ./script.sh
Run Code Online (Sandbox Code Playgroud)

但随后多行变量变为单行变量。

最后,您可以生成一个由 bash 处理的临时文件,并在运行任何命令之前获取它:

SHELL=bash

all: .env-export
    . .env-export && ./script.sh

.env-export: .env
    sed -ne '/^export / {p;d}; /.*=/ s/^/export / p' .env > .env-export
Run Code Online (Sandbox Code Playgroud)

哦,在这种情况下,多行变量中的新行被弄乱了。您需要另外引用它们。

最后,您可以export使用上述sed命令添加到 .env 中,然后执行以下操作:

SHELL=bash
%: .env-export
    . .env-export && make -f secondary "$@"
Run Code Online (Sandbox Code Playgroud)

  • 好的,我想你说服我使用外部工具。感谢您详细的回答! (3认同)

pri*_*yGK 5

您可以通过创建函数和目标来加载每个目标的特定 .env 文件,以便在必要时将其与其他目标一起使用。这里作为示例:

define setup_env
    $(eval ENV_FILE := $(1).env)
    @echo " - setup env $(ENV_FILE)"
    $(eval include $(1).env)
    $(eval export)
endef

devEnv: 
    $(call setup_env, dev)

prodEnv: 
    $(call setup_env, prod)

clean:
    rm -rf  bin/

build: clean
    GOOS=linux GOARCH=amd64 go build -o bin/ ./cmd/...

dev: build devEnv
    cd cmd/api && ./../../bin/api
 
migrate-dev-db: devEnv
    sh +x database/migration/migrate.sh dev

migrate-prod-db: prodEnv
    sh +x database/migration/migrate.sh


deploy: prodEnv
    sh +x script/deployment/production/ec2-deploy.sh
Run Code Online (Sandbox Code Playgroud)