在 Jenkinsfile shell 中转义 JSON 字符串
Escaping JSON string inside Jenkinsfile shell
我正在尝试转义 jenkinsfile 中的 json-string,但我在网上查看的示例有点复杂。
sshagent(credentials: ['keypair']) {
sh """
ssh ansible@ansible-server \
'
# vars
src_env="${params.source_env}"
dest_env="${params.destination_env}"
src_prefix="${params.source_s3_prefix}"
dest_prefix="${params.destination_s3_prefix}"
region="${region}"
ch="${ch}"
aws_account="${aws_account}"
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-${ch}-${dest_env} \
--task-definition $td_id \
--region ${region} \
--overrides {\\"containerOverrides\\": [{\\"name\\": \\"s3-sync\\", \\"environment\\": [{\\"name\\": \\"SRC_ENV\\", \\"value\\": \\"$${src_env}\\"}, {\\"name\\": \\"DEST_ENV\\", \\"value\\": \\"$${dest_env}\\"}, {\\"name\\": \\"SRC_PREFIX\\", \\"value\\": \\"$${src_prefix}\\"}, {\\"name\\": \\"DEST_PREFIX\\", \\"value\\": \\"$${dest_prefix}\\"}]}], \\"taskRoleArn\\": \\"arn:aws:iam::$${aws_account}:role/$${ch}-$${dest_env}\\"} \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
}
因此,问题是要转义以下 json 字符串:
--overrides {\\"containerOverrides\\": [{\\"name\\": \\"s3-sync\\", \\"environment\\": [{\\"name\\": \\"SRC_ENV\\", \\"value\\": \\"$${src_env}\\"}, {\\"name\\": \\"DEST_ENV\\", \\"value\\": \\"$${dest_env}\\"}, {\\"name\\": \\"SRC_PREFIX\\", \\"value\\": \\"$${src_prefix}\\"}, {\\"name\\": \\"DEST_PREFIX\\", \\"value\\": \\"$${dest_prefix}\\"}]}], \\"taskRoleArn\\": \\"arn:aws:iam::$${aws_account}:role/$${ch}-$${dest_env}\\"} \
感谢任何帮助?我尝试了很多不同的方法,但似乎没有任何效果。
我建议不要在 ssh 之后尝试评估所有变量,而是将 shh 命令计算为 shell 脚本评估的一部分。
在 groovy 中,当您使用双引号(单引号或三引号)时,任何跟在 $
之后的内容都会得到 evaluated/replaced。因此,您只需在 shell 脚本中使用的每个变量前添加一个 $
,然后在 shell 脚本运行之前就对变量进行求值。您还需要转义任何您不想作为字符串处理的一部分进行评估的 $
。
对于 json blob,我建议在 shell 脚本之外创建一个包含覆盖的映射,然后将该变量转换为 json 字符串。这样您就不必担心使用正确数量的 \
(尽管您可以在三引号字符串中使用单引号而无需转义)并且您的管道文件更具可读性。
我会这样写:
sshagent(credentials: ['keypair']) {
// ch is defined is defined somewhere in the pipeline
// aws_account is also defined somewhere in the pipeline
def overrides = [
containerOverrides: [
[
environment: [
[
name: "SRC_ENV",
value: params.source_env
],
[
name: "DEST_ENV",
value: params.destination_env
],
[
name: "SRC_PREFIX",
value: params.source_s3_prefix
],
[
name: "DEST_PREFIX",
value: params.destination_s3_prefix
]
],
name: "s3-sync"
]
],
taskRoleArn: "arn:aws:iam::${aws_account}:role/${ch}-${params.destination_env}"
]
sh """
ssh ansible@ansible-server \
'
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-${ch}-${params.destination_env} \
--task-definition $td_id \
--region ${region} \
--overrides ${groovy.json.JsonOutput.toJson(overrides)} \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
}
请注意,我没有转义任何我希望字符串处理替换的变量,我只转义了
task_id=$(aws ecs run-task \
以便 aws ecs run-task ...
在执行 ssh 脚本时运行(而不是在评估字符串时)。
根据Vasiliki Siakka的回答,我事先解析了json参数,对json字符串中的双引号进行了转义,以免在ssh命令中被去掉。因此,对我有用的解决方案如下:
sshagent(credentials: ['keypair']) {
// ch is defined is defined somewhere in the pipeline
// aws_account is also defined somewhere in the pipeline
def overrides = [
containerOverrides: [
[
environment: [
[
name: "SRC_ENV",
value: params.source_env
],
[
name: "DEST_ENV",
value: params.destination_env
],
[
name: "SRC_PREFIX",
value: params.source_s3_prefix
],
[
name: "DEST_PREFIX",
value: params.destination_s3_prefix
]
],
name: "s3-sync"
]
],
taskRoleArn: "arn:aws:iam::${aws_account}:role/${ch}-${params.destination_env}"
]
def parsed_overrides = groovy.json.JsonOutput.toJson(overrides).replace("\"", "\\"")
sh """
ssh ansible@ansible-server \
'
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-${ch}-${params.destination_env} \
--task-definition $td_id \
--region ${region} \
--overrides "${parsed_overrides}" \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
}
我正在尝试转义 jenkinsfile 中的 json-string,但我在网上查看的示例有点复杂。
sshagent(credentials: ['keypair']) {
sh """
ssh ansible@ansible-server \
'
# vars
src_env="${params.source_env}"
dest_env="${params.destination_env}"
src_prefix="${params.source_s3_prefix}"
dest_prefix="${params.destination_s3_prefix}"
region="${region}"
ch="${ch}"
aws_account="${aws_account}"
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-${ch}-${dest_env} \
--task-definition $td_id \
--region ${region} \
--overrides {\\"containerOverrides\\": [{\\"name\\": \\"s3-sync\\", \\"environment\\": [{\\"name\\": \\"SRC_ENV\\", \\"value\\": \\"$${src_env}\\"}, {\\"name\\": \\"DEST_ENV\\", \\"value\\": \\"$${dest_env}\\"}, {\\"name\\": \\"SRC_PREFIX\\", \\"value\\": \\"$${src_prefix}\\"}, {\\"name\\": \\"DEST_PREFIX\\", \\"value\\": \\"$${dest_prefix}\\"}]}], \\"taskRoleArn\\": \\"arn:aws:iam::$${aws_account}:role/$${ch}-$${dest_env}\\"} \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
}
因此,问题是要转义以下 json 字符串:
--overrides {\\"containerOverrides\\": [{\\"name\\": \\"s3-sync\\", \\"environment\\": [{\\"name\\": \\"SRC_ENV\\", \\"value\\": \\"$${src_env}\\"}, {\\"name\\": \\"DEST_ENV\\", \\"value\\": \\"$${dest_env}\\"}, {\\"name\\": \\"SRC_PREFIX\\", \\"value\\": \\"$${src_prefix}\\"}, {\\"name\\": \\"DEST_PREFIX\\", \\"value\\": \\"$${dest_prefix}\\"}]}], \\"taskRoleArn\\": \\"arn:aws:iam::$${aws_account}:role/$${ch}-$${dest_env}\\"} \
感谢任何帮助?我尝试了很多不同的方法,但似乎没有任何效果。
我建议不要在 ssh 之后尝试评估所有变量,而是将 shh 命令计算为 shell 脚本评估的一部分。
在 groovy 中,当您使用双引号(单引号或三引号)时,任何跟在 $
之后的内容都会得到 evaluated/replaced。因此,您只需在 shell 脚本中使用的每个变量前添加一个 $
,然后在 shell 脚本运行之前就对变量进行求值。您还需要转义任何您不想作为字符串处理的一部分进行评估的 $
。
对于 json blob,我建议在 shell 脚本之外创建一个包含覆盖的映射,然后将该变量转换为 json 字符串。这样您就不必担心使用正确数量的 \
(尽管您可以在三引号字符串中使用单引号而无需转义)并且您的管道文件更具可读性。
我会这样写:
sshagent(credentials: ['keypair']) {
// ch is defined is defined somewhere in the pipeline
// aws_account is also defined somewhere in the pipeline
def overrides = [
containerOverrides: [
[
environment: [
[
name: "SRC_ENV",
value: params.source_env
],
[
name: "DEST_ENV",
value: params.destination_env
],
[
name: "SRC_PREFIX",
value: params.source_s3_prefix
],
[
name: "DEST_PREFIX",
value: params.destination_s3_prefix
]
],
name: "s3-sync"
]
],
taskRoleArn: "arn:aws:iam::${aws_account}:role/${ch}-${params.destination_env}"
]
sh """
ssh ansible@ansible-server \
'
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-${ch}-${params.destination_env} \
--task-definition $td_id \
--region ${region} \
--overrides ${groovy.json.JsonOutput.toJson(overrides)} \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
}
请注意,我没有转义任何我希望字符串处理替换的变量,我只转义了
task_id=$(aws ecs run-task \
以便 aws ecs run-task ...
在执行 ssh 脚本时运行(而不是在评估字符串时)。
根据Vasiliki Siakka的回答,我事先解析了json参数,对json字符串中的双引号进行了转义,以免在ssh命令中被去掉。因此,对我有用的解决方案如下:
sshagent(credentials: ['keypair']) {
// ch is defined is defined somewhere in the pipeline
// aws_account is also defined somewhere in the pipeline
def overrides = [
containerOverrides: [
[
environment: [
[
name: "SRC_ENV",
value: params.source_env
],
[
name: "DEST_ENV",
value: params.destination_env
],
[
name: "SRC_PREFIX",
value: params.source_s3_prefix
],
[
name: "DEST_PREFIX",
value: params.destination_s3_prefix
]
],
name: "s3-sync"
]
],
taskRoleArn: "arn:aws:iam::${aws_account}:role/${ch}-${params.destination_env}"
]
def parsed_overrides = groovy.json.JsonOutput.toJson(overrides).replace("\"", "\\"")
sh """
ssh ansible@ansible-server \
'
# Run ECS task
echo "---- Run ECS task ----"
task_id=$(aws ecs run-task \
--cluster cluster-${ch}-${params.destination_env} \
--task-definition $td_id \
--region ${region} \
--overrides "${parsed_overrides}" \
--query 'tasks[0].taskArn' \
--output text | cut -d'/' -f 2)
'
"""
}