Makefile 简化运维操作
背景
最近在项目测试时,由于需要在不同场景下切换,导致有多个 docker-compose.yml 存在,而每次启动/停止都得用 -f 指定目标文件,这样操作太过繁琐,就想利用 Makefile 简化操作,实现 make aaa start,实现 aaa 的 启动,make bbb stop 实现 bbb 的停止这样的效果
实现
调研了下,可以通过 Makefile 中的模块处理实现,具体如下
1 | # 定义一个变量来存储模块名称 |
在这个 Makefile 中:
MODULE变量存储了模块名称$(MAKECMDGOALS):这是一个内置变量,它包含了在命令行中传递给make的目标(targets)。例如,如果在命令行中执行make clean all,那么$(MAKECMDGOALS)的值就是clean all$(firstword ...):这是一个函数,用于从给定的参数中提取第一个单词。它会返回传入参数中的第一个字符串
$(eval $(MODULE):;@:)- 使用
eval动态创建一个名为MODULE值的目标(例如aaa),并且该目标没有实际的命令。这样做是为了在 Makefile 中确保该目标存在,但不执行任何操作 ;表示命令结束,但这里没有实际命令要执行,因此后面没有跟随任何有效命令@表示在执行该命令时不打印命令本身:是一个伪命令,表示什么也不做
- 使用
MODULE_RULE- 定义了一个通用规则模板,用于生成每个模块的目标
$(1)是模板中的占位符,它会在后续调用中被具体的模块名替换- 使用
ifeq条件语句来根据模块的不同,执行相应的 Docker Compose 命令
MODULES列表包含所有模块名称$(foreach module,$(MODULES),$(eval $(call MODULE_RULE,$(module))))foreach函数会遍历MODULES中的每个模块名,调用MODULE_RULE模板并生成相应的规则- 结果是为每个模块生成
aaa-start、aaa-stop、bbb-start、bbb-stop、ccc-start和ccc-stop等规则
%: $(MODULE)-%- 这是一个模式规则,表示任何目标(
%)都会依赖于相应的MODULE名称和后缀(例如,aaa-start或aaa-stop) - 当调用
make aaa-start时,Make 会寻找aaa-start目标,并执行它
- 这是一个模式规则,表示任何目标(
@$(MAKE) $@@:表示在执行该命令时不打印命令本身。这对于保持输出整洁很有用。$(MAKE):这是一个特殊变量,表示当前的 Make 命令。使用$(MAKE)可以确保在调用 Make 时使用相同的参数和环境。$@:这是一个自动变量,表示规则中的目标名。在这个上下文中,$@将被替换为当前目标的名称
这样,当你运行 make aaa start、make bbb start、make ccc start 等命令时,它们会执行相应的 Docker Compose 命令
注意:Makefile 中需要使用 tab,而非 空格 作为缩进,否则执行时,会报错类似 Makefile:28: *** missing separator. Stop,vim 可以用 :set list 命令显示空格和制表符,制表符会显示为 ^I,如果不是制表符,可以使用 :%s/^\s\+/\t/g 进行替换
本博客所有文章除特别声明外,均采用 CC BY-NC-SA 4.0 许可协议。转载请注明来自 cv-programmer!




