在单个环境变量中转义命令的多个参数

问题描述 投票:0回答:1

我有一个运行 ansible 的 shell 脚本,它可以采用封装在系统环境变量中的参数

ANSIBLE_ARGS
。 为了论证,我无法更改 shell 脚本以使用位置参数。 所有参数都必须从环境变量中获取。

脚本运行类似于:

ansible-playbook -i localhost, -c local "${ANSIBLE_ARGS}" myplaybook.yaml

当 Ansible args 包含像

-vvvvv
这样的简单参数时,它效果很好。然而,当我给它提供一个更复杂的参数,如
-e {"key":"a value"}
-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.

如何让应用程序正确解释从环境变量传递的命令参数?

bash variables ansible environment-variables arguments
1个回答
0
投票

我有一个运行 ansible 的 shell 脚本,它可以采用封装在系统环境变量中的参数

ANSIBLE_ARGS

将多个参数打包到一个字符串中是一种糟糕的做法,会引起几个不同类别的问题。 在提供数组的 shell(例如 Bash)中,最佳实践是使用数组。 但是,您不能在环境中存储数组。

脚本运行类似于:

ansible-playbook -i localhost, -c local "${ANSIBLE_ARGS}" myplaybook.yaml

当 Ansible args 包含像 -vvvvv 这样的简单参数时,它会起作用 出色地。然而,当我给它提供一个更复杂的参数时,例如 -e {"key":"a value"} 或 -vvvvv -e {"key":"a value"} 它不起作用。

当然不是。 在“更复杂”的情况下,您尝试向

ansible-playbook
命令传递多个参数,但是当您在(双)引号内展开
$ANSIBLE_ARGS
时,结果不会受到分词的影响。 您可以将变量的整个值作为单个参数获得。

如果您确实致力于在单个环境变量中传递多个参数,那么您需要在运行命令之前以某种方式安排将值拆分为其组成元素。 快速而肮脏的方法是扩展未加引号的值:

ansible-playbook -i localhost, -c local ${ANSIBLE_ARGS} myplaybook.yaml

这样做的问题是,扩展变量的结果将通过命令替换、算术扩展、分词和路径名扩展来进一步扩展。 这种方法依赖于将结果分成多个参数的分词,但有时你也可能在你不想要的地方进行分词,再加上某些情况下的其他扩展。

如何让应用程序正确解释从环境变量传递的命令参数?

要对任意参数可靠地做到这一点是非常困难的。 您最好在命令行上将参数传递给主机脚本。

要通过单个环境变量来完成此操作,您需要一种对环境变量的值进行编码的方法,以便您可以(仅)将值拆分为脚本中的数组元素。 执行了这样的拆分为数组值变量

ARGS_ARRAY
后,您将在命令中使用此变体:

ansible-playbook -i localhost, -c local "${ARGS_ARRAY[@]}" myplaybook.yaml

(这也是使用命令行参数的方式。使用参数只会让构建所需的数组变得更容易。可能就像使用

"$@"
一样简单,即使在没有数组的 shell 中也可以工作.)

© www.soinside.com 2019 - 2024. All rights reserved.