Jenkins 管道语法:使用多个引用块时的引用痛点

Jenkins 管道语法:使用多个引用块时的引用痛点

我有一种奇怪的设置,我需要在shJenkinsfile 的一个块中以 docker 容器的形式运行命令。

我所面临的问题具体与awk用于修剪输出的命令有关。

这是命令工作正常当跑的时候直接在 bash shell 上

OPFILENAME=$(docker run -t \
-e AWS_SECRET_ACCESS_KEY='<omitted>' \
-e AWS_ACCESS_KEY_ID='<omitted>' \
-e AWS_DEFAULT_REGION='us-east-1' \
mydockerimage:0.1 \
bash -c "aws s3 ls my-bucket-name/dir/ | sort | tail -n 1 | awk '{print \$4}' ") && \
echo $OPFILENAME

所以我需要通过 Jenkins 管道在远程主机上运行完全相同的东西,下面是一般语法:

pipeline {              
 agent any

 environment {
  BUILDHOST = 'buildhost.example.com' 
  SSHCMD = "ssh -o StrictHostKeyChecking=no jenkins@${env.BUILDHOST}"
 }


stages {
  stage('Get filename from s3') {
    steps { 
      sshagent ( ['ssh_config']) {
        sh """${SSHCMD} '''
            OPFILENAME=\$(sudo docker run -t \
            -e AWS_SECRET_ACCESS_KEY='<omitted>' \
            -e AWS_ACCESS_KEY_ID='<omitted>' \
            -e AWS_DEFAULT_REGION='us-east-1' \
            mydockerimage:0.1 \
            bash -c "aws s3 ls my-bucket-name/dir/ | sort | tail -n 1 | awk '{print \$4}') && \
            echo \$OPFILENAME
            '''
          """
       }
      }
     }
    }
}

这是 Jenkins 抛出的错误:

...bash -c "aws s3 ls my-bucket-name/dir/ | sort | tail -n 1 | awk {print' '}") && echo $OPFILENAME "
                        '
bash: -c: line 1: unexpected EOF while looking for matching `"'
bash: -c: line 3: syntax error: unexpected end of file

注意它是如何转换awk命令的:awk {print' '}

尝试各种更改:...| sort | tail -n 1 | awk \'{print \$4}\'")导致完全相同的错误。

像这样尝试awk "'{print \$4}'"不会抛出错误但在日志中它显示如下:awk "{print' '}"因此所需的 awk 修剪不会发生。哎呀!

所以我知道引用有问题,而且由于我在多行命令中使用了三重引号,所以它变得更加混乱!

我参考了这个要点,试图弄清楚如何做到这一点:https://gist.github.com/Faheetah/e11bd0315c34ed32e681616e41279ef4但仍然遇到一个又一个问题。

注意事项: - 命令必须在sshagent块中和远程主机上运行。命令不能在本地 Jenkins 工作区中运行。

答案1

'{print \$4}'该错误是由于和之间缺少双引号造成的)。 您在原始脚本中有它,但在 Jenkinsfile 中没有。

话虽如此,这是一个非常困难的问题,因为多个进程将剥离/处理引文。首先是 Groovy 本身。然后是 Jenkin 的sh命令(加上命令将启动的 shell 进程),然后是ssh,然后是将启动的远程 shell ssh,然后是bash您启动​​的。其中之一是删除\之前的$4,这会破坏您的 AWK 脚本。

您可以尝试使用awk -f script或使用sed将多个空间折叠为一个然后使用来解决此特定问题cut... | sed -e 's/ +/ /g' | cut -d " " -f 4 | ...

但最终它总是脆弱的。

我强烈建议创建一个脚本文件,将其复制到远程主机并运行ssh bash ./script.sh。这将消除很多麻烦。最重要的是,您将能够从命令行测试和调试脚本,而无需在每次更改后都经过 Jenkins。

或者,将大部分脚本放入自定义 docker 镜像并选择其作为该镜像的默认命令。

使用SSH 管道步骤插件可能会有帮助,因为它有一个选项“sshScript”,它可以将脚本复制到远程服务器,然后在那里执行它:https://github.com/jenkinsci/ssh-steps-plugin#sshscript

相关内容