如何使Ansible正确解析环境变量传递的复杂多命令参数?
问题
现有一个运行Ansible的Shell脚本,通过环境变量ANSIBLE_ARGS接收参数,因限制无法修改脚本改用位置参数,所有参数必须来自该环境变量。脚本执行命令示例:
ansible-playbook -i localhost, -c local "${ANSIBLE_ARGS}" myplaybook.yaml
当ANSIBLE_ARGS为-vvvvv这类简单参数时能正常工作,但传递-e {"key":"a value"}这类复杂参数或组合参数时失效。以下是复现问题的测试脚本及结果:
--- test.sh --- #!/bin/sh ansible -i localhost, -c local "${ANSIBLE_ARGS}" all -m debug -a "var=key" --- end test.sh ---
测试案例:
$ ANSIBLE_ARGS="-e {\"key\":\"a value\"}" ./test.sh localhost | SUCCESS => { "key": "VARIABLE IS NOT DEFINED!" }
$ ANSIBLE_ARGS="-v -e {\"key\":\"a value\"}" ./test.sh usage: ansible [-h] [--version] [-v] .....sic.... ansible: error: unrecognized arguments: - -e {"key":"a value"}
$ ANSIBLE_ARGS="-e={\"key\":\"a value\"} -v" ./test.sh [WARNING]: * Failed to parse localhost, with host_list plugin: We were unable to read either as JSON nor YAML, these are the errors we got from each: JSON: Extra data: line 1 column ......sic.... The error appears to be in '<string>': line 1, column 19, but may be elsewhere in the file depending on the exact syntax problem.
$ ANSIBLE_ARGS="-e={\"key\":\"a value\"} -e={\"foo\":1}" ./test.sh [WARNING]: * Failed to parse localhost, with host_list plugin: We were unable to read either as JSON nor YAML, these are the errors we got from each: JSON: Extra data: line 1 column .... sic .... The error appears to be in '<string>': line 1, column 19, but may be elsewhere in the file depending on the exact syntax problem.
如何让应用正确解析从环境变量传递的命令参数?
解决方案
问题根源在于sh中用双引号包裹${ANSIBLE_ARGS}时,会把整个环境变量内容当作单个参数传递,无法正确拆分带空格或特殊字符的参数。以下是可行的解决方式:
方法1:改用数组传递(需脚本支持bash)
若脚本可改为bash(将#!/bin/sh替换为#!/bin/bash),可将环境变量转为数组后传递,能精准拆分参数:
修改脚本为:
#!/bin/bash IFS=' ' read -r -a args <<< "$ANSIBLE_ARGS" ansible -i localhost, -c local "${args[@]}" all -m debug -a "var=key"
设置环境变量时无需转义双引号:
ANSIBLE_ARGS='-v -e {"key":"a value"}' ./test.sh
方法2:使用eval(兼容sh,注意安全风险)
若必须保留#!/bin/sh,可通过eval重新解析参数,但仅在完全信任环境变量来源的情况下使用,避免命令注入风险:
修改脚本为:
#!/bin/sh eval "ansible -i localhost, -c local $ANSIBLE_ARGS all -m debug -a \"var=key\""
设置环境变量的写法:
ANSIBLE_ARGS='-v -e "{\"key\":\"a value\"}"' ./test.sh # 或用单引号包裹JSON部分简化写法 ANSIBLE_ARGS="-v -e '{\"key\":\"a value\"}'" ./test.sh
方法3:不修改脚本的调整方式(仅部分场景可行)
若完全无法修改脚本,只能调整环境变量传递方式,利用sh的参数拆分特性,但需避免双引号包裹整个参数列表:
ANSIBLE_ARGS='-v -e '\''{"key":"a value"}'\'' ./test.sh
这种方式在复杂参数场景下易出错,优先推荐前两种方法。
内容的提问来源于stack exchange,提问作者Wanderer
相关产品推荐
相关产品推荐

