$@变量正确插值问题:SSM脚本无法传递多参数
问题:SSM Runner脚本处理带参数的命令失败
我的EC2实例上有两个脚本:hello_world.sh(输出“hello world”)和echo.sh(接收并回显参数)。执行ssm_runner.sh dev hello_world.sh能正常运行,但执行ssm_runner.sh dev echo.sh hello时完全失效。原脚本代码如下:
#!/bin/bash TARGET_ENV="$1" shift commandid=$(aws ssm send-command \ --document-name "AWS-RunShellScript" \ --targets Key=tag:Name,Values=$TARGET_ENV \ --parameters '{"commands":["su -c \"./'$@'\" - ec2-user"]}' \ --query 'Command.CommandId' \ --output text) echo $commandid
解决方案
问题根源在于$@的插值逻辑:当传入多个参数(比如echo.sh hello)时,$@会被拆分成独立字段,直接拼进JSON会破坏格式,同时shell引号规则会让参数传递混乱。
以下是修复后的脚本,能正确处理带参数的命令:
#!/bin/bash TARGET_ENV="$1" shift # 对所有后续参数转义,确保空格、特殊字符能正确传递 escaped_cmd=$(printf "%q " "$@") # 构造完整的su执行命令 su_cmd="su -c './$escaped_cmd' - ec2-user" commandid=$(aws ssm send-command \ --document-name "AWS-RunShellScript" \ --targets "Key=tag:Name,Values=$TARGET_ENV" \ --parameters '{"commands":["'"$su_cmd"'"]}' \ --query 'Command.CommandId' \ --output text) echo "$commandid"
关键修改点:
- 参数转义:用
printf "%q " "$@"把每个参数转义成shell可正确解析的格式,哪怕参数包含空格、引号这类特殊字符也不会出错。 - 变量隔离:先把
su的完整命令拼成一个变量,再插入到JSON中,避免直接拼接$@导致的字段拆分问题。 - JSON格式保证:通过
'"$su_cmd"'的写法,把变量值正确嵌入JSON字符串,确保AWS能识别合法的JSON参数。
如果你的参数不会包含特殊字符,也可以用更简洁的写法:
#!/bin/bash TARGET_ENV="$1" shift commandid=$(aws ssm send-command \ --document-name "AWS-RunShellScript" \ --targets "Key=tag:Name,Values=$TARGET_ENV" \ --parameters "commands=[\"su -c './$*' - ec2-user\"]" \ --query 'Command.CommandId' \ --output text) echo "$commandid"
不过第一种带转义的写法兼容性更强,适合各种复杂场景。
内容的提问来源于stack exchange,提问作者joyfuljoy
相关产品推荐
相关产品推荐

