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

问题描述 投票:0回答:6

在 Makefile 中使用

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

如果所提出的解决方案仅适用于

make
,那就太好了,例如不使用任何第三方工具。另外
.env
文件支持多行变量,例如:


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

这就是为什么这个解决方案可能不够。

makefile environment-variables
6个回答
24
投票

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

因此,我们假设有两个文件,

.env
,是技术上正确的 shell 文件:

FOO=bar

BAR="notfoo" # comment
   #comment
MULTILINE="This\nis\nSparta!"
# comment

script.sh

#!/bin/bash
echo FOO=${FOO}
echo BAR=${BAR}
echo -e ${MULTILINE}

一种解决方案是包含

.env
文件,然后确保导出变量:

include .env

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

all:
    ./script.sh

由于 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

但是多行变量将变成单行变量。

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

SHELL=bash

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

.env-export: .env
    sed -ne '/^export / {p;d}; /.*=/ s/^/export / p' .env > .env-export

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

最后,您可以使用上面的

export
命令将
sed
添加到 .env,然后执行以下操作:

SHELL=bash
%: .env-export
    . .env-export && make -f secondary "$@"

23
投票

发现了这个,效果很好:

在 makefile 顶部

ifneq (,$(wildcard ./.env))
    include .env
    export
endif

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


6
投票

您可以通过创建一个函数和目标来为每个目标加载特定的 .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

2
投票

这是 .env 和 makefile 用法示例:

.env

DATABASE_URL=postgres://postgres:[email protected]:5432/my_db_development?sslmode=disable

makefile

include .env

migrate:
    migrate -source file://postgres/migrations \
            -database $(DATABASE_URL) up

1
投票

我遇到了同样的问题,这里是我如何解决它的。

  • 首先,我建议检查
    .env
    文件是否存在,否则
    include
    将引发异常。
  • 其次,请随意将
    .env-example
    文件添加到您的存储库中。
    ENVFILE = .env
    ENVFILE_EXAMPLE = .env-example
    
    # Create the .env file if not exit.
    ifeq ("$(wildcard $(ENVFILE))","")
       $(shell cp $(ENVFILE_EXAMPLE) $(ENVFILE))
    endif
    # Load the environment variables from .env file
    include $(ENVFILE)
    export $(shell sed '/^\#/d; s/=.*//' $(ENVFILE)) 

仅供参考:这种方法也可以处理注释,默认情况下 Makefile 语法不应该这样做。

桑霍伊 - 谢谢


0
投票

如果您愿意使用外部工具,您可以尝试direnv

  1. 将 .env 文件放入您的目录中并在其中填充变量。
  2. 为您的 shell 安装并设置 direnv,将其配置为允许 .env 文件。
  3. 在安装Makefile的目录中运行
    direnv allow .
  4. 从现在开始运行 make 将使用您的环境变量。

我用这个来测试

生成文件:

all:
    echo "Hello ${FOO}"

.env:

FOO=alex

~/.config/direnv/direnv.toml:

load_dotenv=true
© www.soinside.com 2019 - 2024. All rights reserved.