Makefile读取含特殊字符的AWS密钥至变量的问题咨询
问题分析
你的问题核心是Make会解析变量中的特殊字符:
- 密钥里的
$e会被Make当成变量引用,而这个变量不存在,就会被替换为空,所以sUpEr$eCr3t变成了sUpErCr3t; #在Make中是注释标记,从#开始的内容会被直接忽略,导致密钥后半段丢失。
不管用=还是:=赋值,Make的变量解析规则都会生效,所以单纯换赋值方式没用。
解决方案
不需要必须用sed,但转义特殊字符是绕不开的思路,以下是几种可行方案:
方案1:转义特殊字符后存入Make变量
在jq读取密钥的同时,用sed把Make敏感的字符转义:
- 把
$替换成$$(Make中$$会被解析为单个$); - 把
#替换成\#(让Make把#当成普通字符)。
修改你的Makefile变量赋值部分:
vars: $(eval SECRET_FILE := secretfile.json) $(eval USERNAME := $(shell jq -r '.username' $(SECRET_FILE))) # 新增sed转义处理 $(eval PASSWORD := $(shell jq -r '.secret' $(SECRET_FILE) | sed -e 's/\$$/$$$$/g' -e 's/#/\\#/g')) @cat $(SECRET_FILE) @echo "" @jq -r '.secret' $(SECRET_FILE) @echo "user: $(USERNAME)" @echo "pass: $(PASSWORD)"
执行后就能完整输出密钥内容。
方案2:避免将密钥存入Make变量
如果不需要在多个地方复用密钥,直接在需要使用的命令中通过jq读取,绕开Make的变量解析:
vars: $(eval SECRET_FILE := secretfile.json) $(eval USERNAME := $(shell jq -r '.username' $(SECRET_FILE))) @cat $(SECRET_FILE) @echo "" @jq -r '.secret' $(SECRET_FILE) @echo "user: $(USERNAME)" # 直接调用jq获取,不存入变量 @echo "pass: $(shell jq -r '.secret' $(SECRET_FILE))"
这种方式下,Make不会提前解析密钥内容,而是在执行echo命令时直接拿到原始值。
方案3:使用临时环境变量传递
把密钥导出为环境变量,在Make的命令中直接引用环境变量,也能避开Make的变量解析:
vars: $(eval SECRET_FILE := secretfile.json) $(eval USERNAME := $(shell jq -r '.username' $(SECRET_FILE))) # 导出为环境变量 export PASSWORD=$(shell jq -r '.secret' $(SECRET_FILE)); \ cat $(SECRET_FILE); \ echo ""; \ jq -r '.secret' $(SECRET_FILE); \ echo "user: $(USERNAME)"; \ echo "pass: $$PASSWORD"
这里用$$PASSWORD引用环境变量,Make会把$$解析为$,最终调用shell的环境变量$PASSWORD。
内容的提问来源于stack exchange,提问作者scot
相关产品推荐
相关产品推荐

