Jenkins Pipeline 如何输出 StdErr

发表时间 ·

Jenkins Pipeline 中当命令执行错误时,Jenkin 目前还不能返回标准错误信息。本文讨论一种返回标准错误的方法。

举例

以一个简单的命令: ls 为例,说明 sh 的用法。 这里,Pipeline 定义文件如下:

pipeline{
  agent any
  stages{
    stage('sh输出'){
      steps{
        script{
          out = sh(
            label: 'listing directory', 
            returnStdout: true, 
            script: "ls /"
          )
        }
      }
    }
  }
}

正常情况

StdOut

上面这段 Pipeline 定义文件里,重点是中间5行:

out = sh(
  label: 'listing directory', 
  returnStdout: true, 
  script: "ls /"
)

这段话将运行 script 指定的命令,也就是 ls / 的标准输出 StdOut 赋值给 out 变量。正常情况下,得到的是类似下面的:

bin boot dev etc home initrd.img lib lib64 lost+found media mnt ….

异常情况

StdErr

如果命令执行过程出现错误,比如实际执行的命令是针对不存在的路径,比如

out = sh(
  label: 'listing directory', 
  returnStdout: true, 
  script: "ls /ff"
)

这个命令将在标准错误 StdErr 输出下面的信息:

ls: cannot access /ff: No such file or directory

然而标准输出 StdOut 则为空。那么上面这种 Pipeline 写法有两个问题:

  • 不能返回执行命令的标准错误信息,只能返回 StdOut 内容,异常情况下为空
  • 不能抛错,使当前和后续 stage 停止,也不能中断整个任务,更不能将整个任务的状态标记为 Failure

下面就介绍解决方案,以解决上面两个问题。

解决方法

目前的 Jenkins 版本,不提供输出标准错误 StdErr 的方法,不过可以通过下面的做法绕过:

  • 标准错误合并输出到标准输出,再输出到文件
  • 判断运行状态 returnStatus

具体是下面的写法:

pipeline{
  agent any
  stages{
    stage('sh输出'){
      steps{
        script{
          status = sh(
            label: 'listing directory', 
            returnStatus: true,       // 返回运行状态
            script: "ls /ff >test.log 2>&1"   // 合并标准错误 StdErr 到文件和标准输出 StdOut
          )

          out = readFile(file: "test.log")    // 从文件读出标准错误 StdErr 信息
          if (status != 0) {
            error('TEST FAILED.')       // 使当前 stage 运行失败,同时输出错误信息。
          }
        }
      }
    }
  }
}

这里面关键的一步 error() 的用法,见 《Jenkins Declarative Pipeline 语法简介》 。执行了上面的语句之后,整个任务以失败结束:

同时后续的 Stage 都不再执行,从控制台日志里能看到:

Stage skipped due to earlier failure(s)

注意:上面合并标准错误的命令里,两次重定向的顺序不能颠倒,必须先导出到文件 >test.log ,再处理标准错误 2>&1


相关文章   欢迎到 留言板 写下你的看法。
  本页面内容采用 署名协议 CC-BY 授权。欢迎转载,请保留原文链接