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 控制台会输出如下内容:
可以看到,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}"
}
}
}
}
}
执行后输出如下:
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}"
}
}
}
}
}
输出如下:
第一个命令返回 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 中断
输出如下:
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}"
}
}
}
}
}
输出如下:
同时返回 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}"
}
}
}
}
}
输出如下:
5. 总结
本文介绍了 Linux 中标准流(stdout、stderr)和状态码的基本概念,并演示了如何在 Jenkins Pipeline 中使用 sh
步骤执行 Shell 命令,并捕获其输出和状态码。以下是几个关键点:
✅ 使用 returnStdout
可获取 stdout
✅ 使用 returnStatus
可获取状态码
✅ 通过 2>&1
可将 stderr 重定向至 stdout
❌ 不要忘记使用 || true
避免因命令失败中断 pipeline
⚠️ 注意处理输出中的换行符和多余空格,避免解析失败
掌握这些技巧后,你可以更灵活地在 Jenkins Pipeline 中编写 Shell 脚本,并根据执行结果做出更智能的流程控制。