【问题标题】:Makefile running export env having issue运行导出环境的 Makefile 有问题
【发布时间】:2020-05-04 10:36:18
【问题描述】:

我创建了一个Makefile 以从固定 路径导出kubeconfig,例如:

myproj
 - .kube     //folder
     config    //file which contain the config
 - Makefile.  //same level as .kube folder

现在,当我从终端运行 时,它可以工作,我的意思是如果我运行 kubectl get ns 我得到了结果,这意味着它配置成功

export KUBECONFIG=/Users/i33333/projects/app-test/v-app/.kube/config

我已经创建了一个 makefile 目标,如下所示

kube-cfg:
    export KUBECONFIG=$(PWD)/.kube/config

当执行我在终端中看到的目标时

export KUBECONFIG=/Users/i33333/projects/app-test/v-app/.kube/config

与手动操作完全相同,但是当我运行 kubectl get ns

我收到错误:

error: no configuration has been provided, try setting KUBERNETES_MASTER environment variable

我不明白为什么它当我从 makefile 运行它时会起作用,而当我从终端手动运行它时它会起作用?任何的想法 我尝试更改并使用没有帮助的 $(CURRDIR)

更新

我已经尝试过建议的不起作用

KUBECONFIG=$(PWD)/.kube/config


kube-cfg:
    export $(KUBECONFIG)

更新2

如果我这样做

KUBECONFIG := $(PWD)/kube/config.yaml
tgt1:
    @export KUBECONFIG=$(KUBECONFIG) && kubectl get ns

我在运行 makefile tgt1: 时能够看到 ns 但是 如果现在我想从终端运行它kubectl get ns 我得到同样的错误`错误:没有提供配置,尝试设置 KUBERNETES_MASTER 环境变量,我想从 makefile 配置它

【问题讨论】:

标签: linux shell kubernetes makefile gnu-make


【解决方案1】:

问题是makefile recipe 创建了新环境,完成recipe 后销毁。

如果你想在调用 make 后使用 kubernetes 工具,在你的场景中更合适的工具是使用source 命令。它适用于您当前的环境中作为参数传递的脚本中所做的所有更改:

$ source setupenv.sh
$ kubectl get ns # should be no problem
$ make someting # even using kubectl inside make shouldn't be a problem

但是,如果您想在 make 脚本中使用 kubectl,请创建如下内容:

recipe :
      source setupenv.sh && kubectl get ns
# or 
recipe2 :
      export KUBECONFIG=$(PWD)/.kube/config && kubectl get ns

更新

我认为配置文件是一个脚本。所以你应该准备shell脚本设置环境,例如setupenv.sh:

#!/bin/bash
export KUBECONFIG=$(PWD)/.kube/config

【讨论】:

  • 对不起,我不明白,我用路径尝试源,但我得到了错误,你能用我的上下文更新你的答案吗?
  • 我不想在我的 make 中使用 kubectl,我只想配置环境并在终端中使用它
  • 谢谢,所以我必须定义一个附加脚本,我不能从 makefile 运行它?
  • @NinaS 如果你想在 make recipe 中使用它(在make 之前没有source),必须为每个行设置环境。所以我建议在使用之前手动完成。
  • @NinaS 正确,没有办法通过make 做到这一点。这不是make 的缺陷。这是 POSIX/UNIX 系统中所有程序的工作方式。当您启动一个新程序时,该程序会继承父程序的环境。但是,子程序永远不可能修改父程序的环境。该程序是make、新的shell 还是您自己编写的其他程序都没有关系。这是不可能的。 UNIX 存在 50 年来一直如此。
【解决方案2】:

当您运行make 时,配方将在从make 进程派生的shell 中执行。此外,食谱跨越多个,每一行(除非链接到换行符转义)也有自己的 shell 子进程。这实际上意味着,无论在这些 shell 中发生什么(shell 变量分配或导出),都不会影响 make 本身或其他配方行。

例如,您可以定义一个 make 变量(就像您在更新中所做的那样),然后您可以在环境中为您尝试运行的任何命令 (somecmd) 设置它,例如:

some_target:
    export KUBECONFIG=$(KUBECONFIG); somecmd

或:

some_target:
    KUBECONFIG=$(KUBECONFIG) somecmd

在这种情况下,KUBECONFIG 指的是一个 make 变量,就像您在上面定义的那样:

KUBECONFIG := $(PWD)/.kube/config

即像这样:

KUBECONFIG := $(PWD)/.kube/config

all: tgt1 tgt2

tgt1:
        @export KUBECONFIG=$(KUBECONFIG); echo "KUBECONFIG is $${KUBECONFIG}"

tgt2:
        @KUBECONFIG=$(KUBECONFIG) sh -c 'echo KUBECONFIG is $${KUBECONFIG}'

产量:

$ make
KUBECONFIG is /tmp/.kube/config
KUBECONFIG is /tmp/.kube/config

因此,如果您在 make 完成后仍然存在某些问题,则需要将其写出来。例如。一个包装器,例如:

KUBECONFIG := $(PWD)/kube/config.yaml

.PHONY: call

# run callme.sh being the first prerequisite.
call: callme.sh
    ./$<

# creates and sets exec bit on rule target here being callme.sh
callme.sh:
    @echo -e '#!/bin/bash\nKUBECONFIG=$(KUBECONFIG) kubectl get ns' > $@
    chmod +x $@

这使您可以运行make 和目标call 调用包装器...并且您还剩下一个包装器callme.sh,您可以在make 完成后运行。

【讨论】:

  • 谢谢,我应该在$(KUBECONFIG) 中输入什么?
  • 对不起,我在打字时遗漏了一点,语法实际上是关闭的。
  • 不,不要在调用命令之前添加 &amp;&amp; 定义变量,使该变量(将其导出)到命令的环境(并且只有该进程及其子进程)执行。 &amp;&amp;; 那样在管道中拆分两个命令。您要么必须 export 然后调用 (tgt1) 或设置并立即调用 (tgt2)。
  • 但无论如何...这仅适用于在 make 配方中运行任何内容。您不能将导出变量返回到执行它的 shell 中。例如,您可以让它生成一个可以调用的包装脚本。
  • 你认为有办法用 make 来做吗?生成的包装器是什么意思?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-20
  • 1970-01-01
  • 2018-01-25
  • 2014-10-20
  • 2020-12-23
相关资源
最近更新 更多