Jenkins流水线中AWS CLI带Header的命令转义问题求助
问题场景
我们在创建Jenkins流水线时,需要通过AWS SSM向节点下载文件,但始终无法解决命令中的Header转义问题,尝试多种引号、转义符组合均失败。
原命令示例
header='Authorization: Bearer NjA5MDg4Mdsfsdfsdfsdfdsfsddsfsr1223434' aws ssm send-command --instance-ids i-12344556677 --document-name AWS-RunShellScript --parameters "commands=cd /tmp; wget -d --header=${header} https://git.org/projects/files/raw/requirements.txt" --output text --query Command.CommandId --region eu-west-1
报错信息
aws ssm send-command --instance-ids i-1232131212312 --document-name AWS-RunShellScript --parameters 'commands=cd /tmp; wget -d --header='Authorization: Bearer NjA5M33333444444444444444U' https://git.org/projects/files/raw/requirements.txt' --output text --query Command.CommandId --region eu-west-1
使用格式:aws [选项] <命令> <子命令> [<子命令> ...] [参数]
如需查看帮助文本,可运行:aws help
aws <命令> help
aws <命令> <子命令> help未知选项:NjA5M33333444444444444444U, https://git.org/projects/files/raw/requirements.txt
问题原因
核心问题是嵌套引号的转义冲突:当包含空格的header变量代入AWS SSM命令的parameters参数时,Shell解析时会将Bearer令牌和下载URL从wget的参数中拆分出来,误识别为AWS命令的独立选项,从而触发报错。
解决方案
方法一:为Header变量添加包裹引号
直接在${header}外层添加单引号,确保整个Header作为wget的完整参数传递,同时保持外层双引号包裹commands内容:
header='Authorization: Bearer NjA5MDg4Mdsfsdfsdfsdfdsfsddsfsr1223434' aws ssm send-command --instance-ids i-12344556677 --document-name AWS-RunShellScript --parameters "commands=cd /tmp; wget -d --header='${header}' https://git.org/projects/files/raw/requirements.txt" --output text --query Command.CommandId --region eu-west-1
方法二:使用JSON格式传递参数
AWS CLI支持JSON格式定义参数,能彻底规避Shell引号转义问题,是最稳定的方案:
header='Authorization: Bearer NjA5MDg4Mdsfsdfsdfsdfdsfsddsfsr1223434' aws ssm send-command \ --instance-ids i-12344556677 \ --document-name AWS-RunShellScript \ --parameters '{"commands": ["cd /tmp; wget -d --header=\"'${header}'\" https://git.org/projects/files/raw/requirements.txt"]}' \ --output text \ --query Command.CommandId \ --region eu-west-1
也可以将命令拆分为数组形式,可读性更强:
header='Authorization: Bearer NjA5MDg4Mdsfsdfsdfsdfdsfsddsfsr1223434' aws ssm send-command \ --instance-ids i-12344556677 \ --document-name AWS-RunShellScript \ --parameters '{"commands": ["cd /tmp", "wget -d --header=\"'${header}'\" https://git.org/projects/files/raw/requirements.txt"]}' \ --output text \ --query Command.CommandId \ --region eu-west-1
方法三:Jenkins流水线中的安全写法
如果是在Jenkins的Shell步骤中执行,建议用单引号包裹整个Shell块,或使用Jenkins环境变量传递Header:
sh ''' header='Authorization: Bearer NjA5MDg4Mdsfsdfsdfsdfdsfsddsfsr1223434' aws ssm send-command --instance-ids i-12344556677 --document-name AWS-RunShellScript --parameters "commands=cd /tmp; wget -d --header='${header}' https://git.org/projects/files/raw/requirements.txt" --output text --query Command.CommandId --region eu-west-1 '''
使用环境变量的方式更安全,避免直接拼接:
env.HEADER = 'Authorization: Bearer NjA5MDg4Mdsfsdfsdfsdfdsfsddsfsr1223434' sh ''' aws ssm send-command --instance-ids i-12344556677 --document-name AWS-RunShellScript --parameters "commands=cd /tmp; wget -d --header='${HEADER}' https://git.org/projects/files/raw/requirements.txt" --output text --query Command.CommandId --region eu-west-1 '''
内容的提问来源于stack exchange,提问作者Dave Shaw

