1. 概述

Jenkins Pipeline 提供了灵活的结构,可以与多种工具和平台集成,以执行我们的持续集成/持续部署(CI/CD)流程。一个常见的使用场景是执行原生操作系统命令。Jenkins 提供了简洁的语法,让我们可以在 pipeline 代码中内联执行这些命令。

在本文中,我们将介绍 Linux 标准流(stdout、stderr)的基本概念,并演示如何在 Jenkins Pipeline 中使用 sh 步骤执行 Shell 命令,以及如何捕获其标准输出、错误输出和状态码。

2. 什么是 stdout、stderr 与状态码

Linux 标准流是程序与其运行环境之间通信的通道。它们用于程序与终端或其他程序之间的数据传输。stdout 与 stderr 是其中最常见的两种标准流。

状态码(Exit Code)则是命令执行完成后返回的一个整数值,用于表示执行是否成功

下面我们将分别介绍这三者的作用。

2.1 标准输出(stdout)

标准输出流,即 stdout,用于捕获命令执行后产生的正常输出。它通常连接到终端,将命令的输出显示在终端上。例如,当我们使用 echo 命令时,输出就是通过 stdout 传递的:

$ echo "this is coming from stdout"
this is coming from stdout

上面的例子中,echo 命令的输出被 stdout 捕获,并输出到终端。

2.2 标准错误(stderr)

标准错误流,即 stderr,用于捕获命令执行过程中产生的错误信息。当命令执行失败时,错误信息会被 stderr 捕获并输出到终端:

$ ls noSuchFile
ls: cannot access 'noSuchFile': No such file or directory

上面的例子中,我们尝试列出一个不存在的文件,系统返回了错误信息,该信息就是通过 stderr 输出的。

2.3 状态码(Exit Code)

命令执行完成后,会返回一个状态码来表示执行结果。状态码是一个 0 到 255 之间的整数,0 表示成功,非零值表示失败

我们可以通过 $? 这个特殊变量查看上一个命令的状态码:

$ echo "this is a successful command"
this is a successful command
$ echo $?
0
$ ls unsuccessful
ls: cannot access 'unsuccessful': No such file or directory
$ echo $?
2

上面的例子中,echo 成功执行,返回 0;而 ls 失败,返回 2。

3. 使用 Jenkins 的 sh 步骤

Jenkins 提供了 sh 步骤用于在 pipeline 中执行 Linux 命令。**sh 会在当前执行节点上运行指定的 Shell 命令**。

以下是一个简单的 Jenkins Pipeline 示例:

pipeline {
    agent any
    stages {
        stage("use Linux commands"){
            steps {
                script {
                  sh "echo successful command"
                  sh "ls noSuchFile"
                }
            }
        }
    }
}

上面的代码中,我们执行了两个命令:echo 成功,ls 失败。

执行后,Jenkins 控制台会输出如下内容:

Jenkins sh step

可以看到,stdout、stderr 以及失败命令的状态码都会被打印到日志中。

4. 从 sh 脚本中返回 stdout、stderr 与状态码

除了将输出打印到控制台,我们还可以将 stdout、stderr 和状态码返回到 pipeline 变量中,以实现更灵活的流程控制。

4.1 返回 stdout

Jenkins 的 sh 步骤提供了 returnStdout 参数,用于返回命令的标准输出:

pipeline {
    agent any
    stages {
        stage("use Linux commands"){
            steps {
                script {
                def stdout = sh script: "echo returned output", returnStdout: true
                print "The stdout is:\n ${stdout}"
                }
            }
        }
    }
}

执行后输出如下:

return stdout in jenkins

4.2 返回状态码

使用 returnStatus 参数可获取命令的状态码:

pipeline {
    agent any
    stages {
        stage("use Linux commands"){
            steps {
                script {
                def status = sh script: "echo returned output", returnStatus: true
                print "The status code is:\n ${status}"
                status = sh script: "ls noSuchFile", returnStatus: true
                print "The status code is:\n ${status}"
                }
            }
        }
    }
}

输出如下:

return command status in jenkins

第一个命令返回 0,第二个命令返回 2。

4.3 返回 stderr

虽然 sh 没有直接返回 stderr 的参数,但我们可以通过重定向 stderr 到 stdout 的方式实现:

pipeline {
    agent any
    stages{
        stage("use Linux commands"){
            steps{
                script{
                    def stderr = sh script:"ls noSuchFile 2>&1 || true", returnStdout: true
                    print "The stderr is:\n ${stderr}"
                }
            }
        }
    }
}

解释:

  • 2>&1:将 stderr(文件描述符 2)重定向到 stdout(文件描述符 1)
  • || true:确保命令返回 0,避免 pipeline 中断

输出如下:

return stderr to jenkins

4.4 在一个步骤中同时返回 stdout/stderr 与状态码

我们可以将 stdout 或 stderr 与状态码合并返回,以减少重复调用:

同时返回 stdout 与状态码

pipeline {
    agent any
    stages{
        stage("use Linux commands"){
            steps{
                script{
                    def stdout_status = sh script:'echo "this is stdout" && echo "$?" ', returnStdout: true
                    print "The stdout and status is:\n ${stdout_status}"
                }
            }
        }
    }
}

输出如下:

jenkins stdout and status

同时返回 stderr 与状态码

pipeline {
    agent any
    stages{
        stage("use Linux commands"){
            steps{
                script{
                    def stderr_status = sh script:'ls noSuchFile 2>&1 || true && echo "$?" ', returnStdout: true
                    print "The stderr and status is:\n ${stderr_status}"
                }
            }
        }
    }
}

输出如下:

jenkins stderr and status

5. 总结

本文介绍了 Linux 中标准流(stdout、stderr)和状态码的基本概念,并演示了如何在 Jenkins Pipeline 中使用 sh 步骤执行 Shell 命令,并捕获其输出和状态码。以下是几个关键点:

✅ 使用 returnStdout 可获取 stdout
✅ 使用 returnStatus 可获取状态码
✅ 通过 2>&1 可将 stderr 重定向至 stdout
❌ 不要忘记使用 || true 避免因命令失败中断 pipeline
⚠️ 注意处理输出中的换行符和多余空格,避免解析失败

掌握这些技巧后,你可以更灵活地在 Jenkins Pipeline 中编写 Shell 脚本,并根据执行结果做出更智能的流程控制。


原始标题:Return Stdout, Stderr, and Status From Jenkins sh Script