You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

自定义共享Jenkins库返回sh命令结果而非预期计算结果求助

Jenkins共享库函数返回sh执行结果而非计算结果的问题

环境

  • 基于自定义共享库的Jenkins声明式多分支流水线
  • 用于处理提交信息的自定义库函数

代码示例

简化后的声明式流水线

@Library('<my-library>@<specific-version>') _

pipeline {
    options {
        timeout(time: 30)
    }

    agent {
        label "<agent>"
    }
    
    stages {
        <...>
        stage('Problem stage'){
            steps{
                script {
                  result = libraryFunctionCall()
                }
            }
        }
        <...>
    }    
}

简化后的库函数

@NonCPS
def call() {
    <definitions and checks, works fine>
    def result = "test"
    def data = getData(param)
    
    result = < some calculation based on received data >

    return result
}

@NonCPS
def getData(param) {
    return sh(returnStdout: true,
            script: """ 
                    curl < ... >
            """).trim()
}

问题

库函数最终返回的是sh命令的执行结果,而非基于该数据计算后的result值。

版本信息

  • Jenkins 2.401.1
  • Pipeline Utility Steps 2.15.4

解决方法

问题核心是**@NonCPS注解的错误使用**:

  1. Jenkins流水线的CPS机制要求sh这类流水线步骤必须在CPS上下文中执行,而@NonCPS会强制函数脱离CPS上下文,导致sh的执行逻辑异常,直接返回了其执行结果而非后续计算值。
  2. 调整注解范围即可解决:
    • 移除getData函数上的@NonCPS,因为它需要调用CPS方法sh。
    • 如果call函数中的计算逻辑不需要处理非序列化对象,直接移除它的@NonCPS;如果必须保留@NonCPS(比如复杂的非序列化操作),则把CPS调用和计算逻辑拆分到不同函数中。

修改后的库函数示例(常规场景)

// 移除@NonCPS,让函数在CPS上下文执行
def call() {
    <definitions and checks, works fine>
    def result = "test"
    def data = getData(param)
    
    result = < some calculation based on received data >

    return result
}

// 移除@NonCPS,确保sh能正常执行
def getData(param) {
    return sh(returnStdout: true,
            script: """ 
                    curl < ... >
            """).trim()
}

必须保留@NonCPS的场景

如果call函数的计算逻辑必须脱离CPS上下文,拆分函数:

// 仅保留计算逻辑在@NonCPS函数中
@NonCPS
def calculateResult(data) {
    return < some calculation based on received data >
}

// CPS调用单独放在无注解函数中
def getData(param) {
    return sh(returnStdout: true,
            script: """ 
                    curl < ... >
            """).trim()
}

对应的流水线调整:

script {
    def data = library.getData(param)
    result = library.calculateResult(data)
}

内容的提问来源于stack exchange,提问作者ArtSav

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.16 12:54:53