Jenkins Pipeline 如何输出 StdErr

2019-05-24
标签: JENKINS

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

举例

以一个简单的命令: ls 为例,说明 sh 的用法。 假设使用如下的 pipeline 文件,其中仅包含 ls / 命令

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 /notExist"
)

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

ls: cannot access /notExist: 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, 
            // 合并标准错误 StdErr 到文件和标准输出 StdOut
            script: "ls /ff \>test.log 2>&1" 
          )
          // 从文件读出标准错误 StdErr 信息
          out = readFile(file: "test.log") 
          if (status != 0) {
            // 使当前 stage 运行失败,同时输出错误信息。
            error('TEST FAILED.') 
          }
        }
      }
    }
  }
}

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

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

Stage skipped due to earlier failure(s)

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

(全文完)

如果您对本站内容有疑问或者寻求合作,欢迎 联系邮箱邮箱已到剪贴板

标签: JENKINS

欢迎转载本文,惟请保留 原文出处 ,且不得用于商业用途。
本站 是个人网站,若无特别说明,所刊文章均为原创,并采用 署名协议 CC-BY-NC 授权。