转义Jenkinsfile shell中的JSON字符串

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了转义Jenkinsfile shell中的JSON字符串相关的知识,希望对你有一定的参考价值。

我试图逃避jenkins文件中的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之后尝试评估所有变量,而是在shell脚本评估中计算shh命令。

在groovy中,当你使用双引号(单引号或三引号)时,任何跟随$的内容都将被评估/替换。因此,您可以在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 \

这样在运行ssh脚本时运行aws ecs run-task ...(而不是在评估字符串时)。

另一答案

基于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 shell中的JSON字符串的主要内容,如果未能解决你的问题,请参考以下文章

求教关于shell脚本中参数中的转义空格

如何在 Jenkinsfile 中使用 package.json 的版本号自动重命名“dist”文件夹

javascript 怎么把字符串中的特殊符号转义

对Jenkinsfile语法说不,开源项目Jenkins Json Build挺你

shell中单引号怎么转义

将 shell 转义的参数字符串传递给 Bourne shell 中的子命令