在 Jenkins 管道中,为什么不显示 return 字符串?

In a Jenkins pipeline, why is this not showing the return string?

我有以下脚本管道,可将标签添加到 AWS 中的现有 ECR 图像

node("linux") {
    stage("test") {
        docker.withRegistry("https://0123456789.dkr.ecr.us-east-1.amazonaws.com", "myCreds") {
            String rc = null
            sh """
                aws ecr batch-get-image --repository-name repo-name --image-ids imageTag=1.0.286 --query images[].imageManifest --output text > manifest.json
                cat manifest.json
            """
            try {
                rc = sh(script: """
                          aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://manifest.json
                         """,
                         returnStdout: true).trim()
            }
            catch(err) {
                println "rc=$rc"
            }
        }
    }
}

当我 运行 管道时,我在控制台输出中得到了这个。

+ aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://./manifest.json

An error occurred (ImageAlreadyExistsException) when calling the PutImage operation: Image with digest 'sha256:ff44828207c7c7df75a8be2e08057da438b4b7f3063acab34ea7ebbcb7dd50a6' and tag 'qa-1.0.286' already exists in the repository with name 'repo-name' in registry with id '0123456789'
[Pipeline] echo
rc=null

为什么在控制台输出中是 rc=null 而不是上面的 An error occurred... 字符串?我用这种方式捕获了 shell 脚本输出,但为什么它在这里不起作用?在这种情况下,正确的做法是什么?

问题是 shell 步骤捕获 standard output 并且 aws 客户端将消息打印到 standard error

您可以在命令末尾使用 2>&1 将 stderr 转发到 stdout,例如:

aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://manifest.json 2>&1

但另一个问题是,当sh中的命令失败时,它会抛出异常并且不会将值分配给变量,因此您需要确保命令始终成功,例如添加 || : (如果前一个命令失败则执行一个空命令)

缺点是您需要检查输出变量以检查命令是否失败。

代码段可能如下所示:

String rc = null
sh """
    aws ecr batch-get-image --repository-name repo-name --image-ids imageTag=1.0.286 --query images[].imageManifest --output text > manifest.json
    cat manifest.json
"""

rc = sh(script:
"""
    aws ecr put-image --repository-name repo-name --image-tag qa-1.0.286 --image-manifest file://manifest.json 2>&1 || :
""", returnStdout: true).trim()

if (rc.contains("error occurred")) {
// the command invocation failed
}