Jenkins pipeline中优雅的执行shell/python/groovy脚本

背景

单纯的声明或者脚本式的流水线语法,能力非常有限,只能搭建起整体运行框架。具体每个step的实现细节,多是使用脚本进行的。

鉴于groovy 与 pipeline语法的不稳定性,我的原则是,python/shell 脚本能解决的,不在pipeline中用groovy多做逻辑

如何在pipeline 更好的使用脚本,这里写了几个实践。

groovy脚本使用

这里给一个普通的完整声明式流水线的demo,执行脚本,我们可以直接在steps中执行groovy脚本,也可以用script关键字,形成整体的groovy脚本代码块儿,以便于整体运用,抽象复用等。
这里要注意的是,使用groovy,有一些细节语法问题。
官方groovy语法请参考,使用时阅读,可避免不必要的问题
http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_conditional_operators

pipeline {
    agent any
    stages {
        stage('Example') {
            steps {
                // groovy 脚本
                sh 'echo hello'
                echo 'Hello World'
                script {
                    // groovy 脚本
                    def browsers = ['chrome', 'firefox']
                    for (int i = 0; i < browsers.size(); ++i) {
                        echo "Testing the ${browsers[i]} browser"
                    }
                }
            }
        }
    }
}

在groovy脚本中使用shell

shell脚本是依托在steps中的groovy脚本而被调用。

无输出shell脚本运行

在pipeline中,我们通常用 sh 来执行shell,具体语法见 https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script
无输出的shell 语法如下

// 单引号需要拼接 容易出错 不推荐使用
sh 'mkdir -p ' + VARIABLE
// 三引号支持变量等内容,引号嵌套等 推荐使用
sh """cp ${VARIABLE}/ 'abc' "123" ${VARIABLE_1}/${VARIABLE_2}"""

有输出的shell脚本

获取执行状态
// 执行脚本,并获取脚本的exit状态,针对不同状态,做逻辑
def run_status = sh (
    script: """cd ${ROOT_BIN_PATH} &&  \
           ./run.sh  ${env.var1} '${str_param_1}' """,
        returnStatus:true
)
print run_status
// 失败强制退出
if (run_status != 0) {
    print '脚本执行失败,强制退出'
    sh 'exit 1'
}
获取标准输出
// 这里以判断空文件举例,获取行数
def is_empty_file = sh (
    script: """cat ${PROJECT_ROOT_PATH}/${record_filename}.txt | wc -l""", 
    returnStdout: true
).trim()
print 'is_empty_file: ' + is_empty_file
if ( is_empty_file == '0') {
    print '此次录制生成数据文件为空文件,不能上传生成或者更新case!可在reporter 里面查看原先的请求数据文件。'
    sh 'exit 1'
}

使用python 脚本

从远端git拉取并执行python脚本

如果我们把脚本维护在常用仓库里面,这样可以作为依赖包用于pipeline中,这要比维护在机器上有两个特点

  1. 迁移性更好
  2. 维护,调试都更方便,支持参数式指定脚本分支,更灵活
script {
    // 对照版本的分支,如果传入的是master 默认替换成最新上线的commit
    if (express) {
        dir ('./script') {
            // 利用git 获取python工具脚本
            git branch: 'master', credentialsId: 'your_git_credential', url: 'git@repository.git'
            script {
                env.result = sh(script: """echo `python ./path/act.py ${param}` | awk '{print \$NF}' """, returnStdout: true, returnStatus: false).trim()
                print '结果: ' + env.result
            }
        }
    }                    
}

groovy解析json,更丰富的与python脚本交互

如果python脚本产生的数据比较复杂,这里建议在python脚本中序列化成json,保存在文件中,后者这机print到标准输出,以供groovy使用
这里给下解析的串联

python文本 举例

#!/usr/bin/python
import json
a = {}
a['name'] = 'John Doe'
# 方式1 输出到标准输出
print(json.dumps(a))

# 方式2 输出到文件
format_json_str = json.dumps(a, default=lambda o: o.__dict__, indent=2).decode('unicode-escape')
with open(./python_result.json, 'a+') as f:
    f.write(format_json_str)

groovy文本

// 引用在文件最上面,不放在script中
import groovy.json.JsonSlurper

def json_output = sh(script: """python ./act.py""", returnStdout: true).trim()


def result_json = new JsonSlurper()
// 方法1
def result_map = jsonSlurper.parseText(json_output)
// 方法2
def result_map = readJSON file:'./python_result.json'

print result_map.name

参考

  1. 《Jenkins2 权威指南》
  2. groovy http://docs.groovy-lang.org/latest/html/documentation/core-operators.html#_conditional_operators
  3. https://jenkins.io/doc/
  4. https://jenkins.io/doc/pipeline/steps/workflow-durable-task-step/#sh-shell-script
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 206,839评论 6 482
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 88,543评论 2 382
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 153,116评论 0 344
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 55,371评论 1 279
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 64,384评论 5 374
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,111评论 1 285
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,416评论 3 400
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,053评论 0 259
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,558评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,007评论 2 325
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,117评论 1 334
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,756评论 4 324
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,324评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,315评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,539评论 1 262
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,578评论 2 355
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,877评论 2 345

推荐阅读更多精彩内容