我有一个makefile,我正在尝试获取一个命令,以便有条件地在目标中运行。
如果我这样做:
namespace: ## create the kubernetes namespace
K_DESC := $(shell kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null ; echo $$?);
ifneq ($(K_DESC),0)
kubectl create namespace $(KUBE_NAMESPACE)
else
kubectl describe namespace $(KUBE_NAMESPACE)
endif
我收到错误消息:Makefile:53: *** recipe commences before first target. Stop.
如果我这样做:
namespace: ## create the kubernetes namespace
K_DESC := $(shell kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null ; echo $$?);
ifneq ($(K_DESC),0)
kubectl create namespace $(KUBE_NAMESPACE)
else
kubectl describe namespace $(KUBE_NAMESPACE)
endif
我收到错误消息:K_DESC := 0;
/bin/sh: 1: K_DESC: not found
Makefile:51: recipe for target 'namespace' failed
make: *** [namespace] Error 127
不知道还可以尝试什么,试图解决一个问题会困扰另一个问题。
答案 0 :(得分:1)
如果您真正想做的是有条件地执行命令,则可以执行以下操作:
namespace:
if ./$(SCRIPT) > /dev/null ; \
then kubectl describe namespace $(KUBE_NAMESPACE) ; \
else kubectl create namespace $(KUBE_NAMESPACE); \
fi
(请注意,“ if”之前的空格是一个制表符;所有其他空格都是空格。并不是必须要使用换行符,我将其放在中间以使配方易于阅读。)
如果您真正想做的是为变量分配一个值,然后在一个食谱中全部分支,则将执行此操作:
namespace9:
kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null ; \
K_DESC=$$?; \
if [ $$K_DESC -eq 0 ] ; \
then kubectl describe namespace $(KUBE_NAMESPACE) ; \
else kubectl create namespace $(KUBE_NAMESPACE); \
fi
答案 1 :(得分:0)
您不能在制作配方正文中进行变量分配。尝试按以下顺序进行操作:
K_DESC := $(shell kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null ; echo $$?)
namespace: ## create the kubernetes namespace
ifneq ($(K_DESC),0)
kubectl create namespace $(KUBE_NAMESPACE)
else
kubectl describe namespace $(KUBE_NAMESPACE)
endif
发生“配方在第一个目标之前开始”是因为GNU Make认为这两行实际上是两个规则:
namespace: ## create the kubernetes namespace
K_DESC := $(shell kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null ; echo $$?)
也就是说,它认为您有一个没有构建配方的空规则namespace:
,然后是另一个目标为K_DESC
的规则。
此外,如果namespace
不是实际文件,则应将其标记为伪造目标:
.PHONY: namespace # somewhere above the namespace: rule
否则,Make实际上正在寻找名为namespace
的文件。如果您执行touch namespace
,则make namespace
将停止工作,因为该文件存在!
答案 2 :(得分:-2)
这里有很多错误:
首先,如果您在命令行上输入K_DESC := blah
,则会出现错误K_DESC: not found
。这是因为bash在分配中不使用空格-或使用:=
(假定K_DESC
是程序名称,而:=
和blah
是参数)。接下来,此行设置 shell 变量K_DESC
-而不是makefile变量。这意味着ifneq
是一个 makefile 构造,它不知道您在shell中设置的值(另外还有一些计时问题,因为ifneq
将会是在您的配方运行之前很久就以makefile读取时间运行,因此仍然无济于事。
为此,在运行配方第一行的特定Shell实例中分配了所分配的值。因此,当第一行结束时,该外壳程序退出,并且该变量被忘记(运行第二行的外壳程序实例不知道该变量)。
然后,您要调用$(shell command)
-因为只有一个$
,所以make将假定它是一个make函数,并在读取时进行扩展。相反,您想做$$(command ...)
。 Make将$$
转换为$
,并将其与您要运行的命令一起传递给Shell实例。
所以...要做您想做的事情,您可能想要做:
namespace:
K_DESC=$$(kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null ; echo $$?); \
if [ $$K_DESC == 1 ]; then \
kubectl create namespace $(KUBE_NAMESPACE) \
else \
kubectl describe namespace $(KUBE_NAMESPACE) \
fi
请注意,我在每行的末尾添加了\
,以将它们统一为一个配方行(因此,没有变量脱离上下文)。
或者,更古朴地,您可以这样做:
namespace:
@ kubectl describe namespace $(KUBE_NAMESPACE) > /dev/null 2>&1 \
|| kubectl create namespace $(KUBE_NAMESPACE)
注意-> /dev/null 2>&1
将阻止第一个命令的任何输出(stdout和stderr)。