在被Jenkinsfile折磨疯癫的边缘踏行

14,358 阅读3分钟

最近因为业务需求,开始接触Jenkins,并使用Jenkins完成一部分的打包上传工作,在此之前,简单了解了一下Jenkins,关于Jenkins的相关介绍,可参考我的另外一篇文章:Jenkins学习笔记(一),但是,我没有想到,Jenkins对我的折磨才刚刚开始。。。。。

首先简单介绍一下我面临的业务需求:

编写一个Jenkinsfile,实现远程主机查询,然后加一个条件判断,满足条件则执行,不满足则直接退出。

对,乍一看是一个非常简单的需求,但实现起来就一直报错。

第一次报错:无法识别$

我的第一版代码:

stage("Upload") {
    sh """
        ssh ${SSH_NAME} "
        aws s3 ls s3://xxx/xxx/${RELEASE_VERSION}/.lock --endpoint-url=http://xxx.com
        if [[ $? -ne 0 ]]; then
           aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar --endpoint-url=http://xxx.com
           aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar.md5sum s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar.md5sum --endpoint-url=http://xxx.com
        else
           echo "upload offline-resource failed, the file is locked."
           exit 1
        fi 
        "
    """
}

阅读👆的代码可以发现我的业务逻辑是不是格外之清晰,但是,执行的时候就是报错了。

image.png 根据这个报错原因,我去查询了一下,哦,原来是只要把""" 换成'''就好。

第二次报错:参数无法写入

按照提示,我修改了第二版代码:

stage("Upload") {
    sh '''
        ssh ${SSH_NAME} "
        aws s3 ls s3://xxx/xxx/${RELEASE_VERSION}/.lock --endpoint-url=http://xxx.com
        if [[ $? -ne 0 ]]; then
           aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar --endpoint-url=http://xxx.com
           aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar.md5sum s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar.md5sum --endpoint-url=http://xxx.com
        else
           echo "upload offline-resource failed, the file is locked."
           exit 1
        fi 
        "
    '''
}

这个时候,又出现了新的错误:

image.png 我们可以看到,我们在代码中引入的参数无法写入,又是一阵stack overflow,我明白了,原来是''括起来的值不会被插值解析,只有""括起来的值才能通过$符引入。

为了解决这个问题,我又尝试了把'''换成""",结果又报了第一个错误。

第三次报错:脚本无法执行

在经过第二版错误之后,我尝试了无数的解决方法,例如\n去掉每一行最后的换行符,使用;在一行执行命令等,但是都不行,始终是报第一个错误,$使用错误。 于是,我决定换一个思路,尽然分行不行,那我就把所有的命令写入一个脚本里,然后再执行这个脚本。 就这样子,我写了我的第三版代码:

stage("Upload") {
    sh """
        ssh ${SSH_NAME} "echo '#!/bin/bash' > upload.sh"
        ssh ${SSH_NAME} "echo 'aws s3 ls s3://xxx/xxx/${RELEASE_VERSION}/.lock --endpoint-url=http://xxx.com ' >> upload.sh"
        ssh ${SSH_NAME} "echo 'if [[ \$? -ne 0 ]]; then' >> upload.sh"
        ssh ${SSH_NAME} "echo '  aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar --endpoint-url=http://xxx.com' >> upload.sh"
        ssh ${SSH_NAME} "echo '  aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar.md5sum s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar.md5sum --endpoint-url=http://xxx.com' >> upload.sh"
        ssh ${SSH_NAME} "echo 'else' >> upload.sh"
        ssh ${SSH_NAME} "echo '  echo " the file is locked,upload failed. " ' >> upload.sh"
        ssh ${SSH_NAME} "echo '  exit 1' >> upload.sh"
        ssh ${SSH_NAME} "echo 'fi' >> upload.sh"
        ssh ${SSH_NAME} "chmod +x upload.sh"
        ssh ${SSH_NAME} "bash upload.sh"
    """
}

在写出这版代码前,也踩了许多的坑,这里简单总结一下。

  1. 给脚本文件加执行权限,chmod +x upload.sh
  2. 使用 >> 而不是>往脚本里写入内容,>>是追加内容到文件末尾,>是用新的内容覆盖文件
  3. 报错提示[[]]在sh no found,使用bash upload.sh来执行脚本文件,因为sh是比较低级的,而bash是sh的升级版

这版代码最严重的问题是\$?没有转义成功,如图所示

image.png 本该是$?的地方变成0.$?表示上一次命令的返回值,0表示成功。

因此此处每次都是执行成功,而我们的条件判断语句也就因此失效了。

到了这里,我开始换个思路,不再纠结''和""的区别,不再纠结\$?有没有转义成功的问题,我决定在第三版代码的基础上,避开\$?

第四次没有报错

思考了一下,我们其实并不是一定需要通过$?来判断查询语句是否成功。我们可以把查询结果写入一个文件中,判断该文件是否为空来间接判断查询语句是否成功。

于是就有了我的第四版代码:

stage("Upload") {
    sh """
        ssh ${SSH_NAME} "echo '#!/bin/bash' > upload.sh"
        ssh ${SSH_NAME} "echo 'aws s3 ls s3://xxx/xxx/${RELEASE_VERSION}/.lock --endpoint-url=http://xxx.com > is_lock.sh' >> upload.sh"
        ssh ${SSH_NAME} "echo 'if [[ -s is_lock.sh ]]; then' >> upload.sh"
        ssh ${SSH_NAME} "echo '  echo " the file is locked,upload failed. " ' >> upload.sh"
        ssh ${SSH_NAME} "echo '  exit 1' >> upload.sh"
        ssh ${SSH_NAME} "echo 'else' >> upload.sh"
        ssh ${SSH_NAME} "echo '  aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar --endpoint-url=http://xxx.com' >> upload.sh"
        ssh ${SSH_NAME} "echo '  aws s3 cp ${PACKAGE_PATH}/${PACKAGE_NAME}.tar.md5sum s3://xxx/xxx/${RELEASE_VERSION}/${PACKAGE_NAME}.tar.md5sum --endpoint-url=http://xxx.com' >> upload.sh"
        ssh ${SSH_NAME} "echo 'fi' >> upload.sh"
        ssh ${SSH_NAME} "chmod +x upload.sh"
        ssh ${SSH_NAME} "bash upload.sh"
    """
}

最后,终于执行成功了。

image.png

总结一下

复盘写到这里也差不多结束了,写一下经过此次事情的一些小的收获:

  1. 做事情之前可以先花点时间想清楚自己要做什么,可以把思路按1,2,3点这样子列出来
  2. 事情无法推进时,可以先停下来,做一下思路整理,整理目前做了哪些事情,取得了哪些效果,像在这次事件中,我一开始没有整理思路,而是盲目地尝试,后来停下来整理了工作思路,明确了排查的路径
  3. 事情无法推进时,可以明确一下自己到底要做什么事情。在这次事件中,我一开始的目标是上传成功。但因为$的原因一直报错,我的目标不知不觉间就变成了寻找解决$报错的方法,但其实这个并不是我的最终目标,我完全可以绕过这个错误,采用其他的方法解决问题