如何使 Jenkins 日志更可读
创始人
2024-03-02 07:20:32
0

Jenkins 的默认日志难以阅读,但日志本不必如此。

Jenkins 是一个自由开源的自动化服务器,用于构建、测试和部署代码。它是 持续集成 Continuous Integration (CI)、 持续交付 Continuous Delivery (CD)的基础,可以为开发人员每天节约几小时,并保护他们免受失败的代码上线的影响。一旦代码失效或开发人员需要查看测试输出时,Jenkins 提供了日志文件以供检查。

默认的 Jenkins 管道 Pipeline 日志可能难以阅读。这篇关于 Jenkins 日志的基础知识的总结文章提供了一些技巧(和代码),说明了如何提升它们的可读性。

你获得什么

Jenkins 管道分为 几个阶段。Jenkins 自动记录每个阶段的开始,记录内容如下:

[Pipeline] // stage
[Pipeline] stage (hide)
[Pipeline] { (Apply all openshift resources)
[Pipeline] dir

上文显示的内容没有太大区分度,重要的内容(如阶段的开始)未突出显示。在多达数百行的管道日志中,要找到一个阶段的起始和另外一个阶段的终止位置可能会很艰巨。当随意浏览日志寻找一个特定的阶段的时候,这种艰巨尤其明显。

Jenkins 管道是由 Groovy 和 Shell 脚本混合编写的。在 Groovy 代码中,日志记录很少。很多时候,日志是由命令中的不起眼的文本组成,没有详细信息。在 Shell 脚本中,打开了调试模式(set -x),所以每条命令都会被完全 具现化 realized (变量被解除引用并打印出数值)并详细记录,输出也是如此。

鉴于日志可能有很多内容,通读日志获取相关信息可能很繁琐。由于在管道中被处理,并跟着一个 Shell 脚本的 Groovy 日志可读性差,它们很多时候缺少上下文:

[Pipeline] dir
Running in /home/jenkins/agent/workspace/devop-master/devops-server-pipeline/my-repo-dir/src
[Pipeline] { (hide)
[Pipeline] findFiles
[Pipeline] findFiles
[Pipeline] readYaml
[Pipeline] }

我可以知道我正在使用的目录,并且知道我正在使用 Jenkins 的步骤搜索文件、读取 YAML 文件。但是我在寻找什么?我找到并读取的内容是什么?

能做什么?

我很高兴你这么问,因为这里有一些简单的做法和一些小的代码片段可以提供帮助。首先,代码如下:

def echoBanner(def ... msgs) {
   echo createBanner(msgs)
}

def errorBanner(def ... msgs) {
   error(createBanner(msgs))
}

def createBanner(def ... msgs) {
   return """
       ===========================================

       ${msgFlatten(null, msgs).join("\n        ")}

       ===========================================
   """
}

// flatten function hack included in case Jenkins security
// is set to preclude calling Groovy flatten() static method
// NOTE: works well on all nested collections except a Map
def msgFlatten(def list, def msgs) {
   list = list ?: []
   if (!(msgs instanceof String) && !(msgs instanceof GString)) {
       msgs.each { msg ->
           list = msgFlatten(list, msg)
       }
   }
   else {
       list += msgs
   }

   return  list
}

将这段代码添加到每个管道的末尾,也可以 加载一个 Groovy 文件 或者使其成为 Jenkins 共享库 的一部分,这样更有效。

在每个阶段起始处(或者在阶段中的特定位置),只需调用 echoBanner

echoBanner("MY STAGE", ["DOING SOMETHING 1", "DOING SOMETHING 2"])

你的 Jenkins 日志会展示如下:

    ===========================================

    MY STAGE
    DOING SOMETHING 1
    DOING SOMETHING 2

    ===========================================

这个横幅很容易从日志中分辨出来。当正确使用它们时,它们还有助于界定管道流,并且可以很好的将日志分解开来进行阅读。

我已经在某些地方专业地使用这些代码一些时间了。在帮助管道日志更易读和流程更易理解方面,反馈是非常积极的。

上述的 errorBanner 方法以相同的方式工作,但是它会立即使脚本失效。这有助于突显失败的位置与原因。

最佳实践

  1. 在你的 Groovy 代码中大量使用 echo Jenkins 步骤来通知用户你在做什么。这些也可以帮助记录你的代码。
  2. 使用空的日志语句(Groovy 中空的 echo 步骤、echo '' 或 Shell 中的 echo)来分割输出,提高可读性。你可能在你的代码中为同样的目的使用空行。
  3. 避免在脚本中使用 set +x 的陷阱,因为它隐藏了日志记录已执行的 Shell 语句。它并没有清理你的日志,而是使你的管道成为一个黑盒子,隐藏了管道正在做的行为以及出现的任何错误。确保管道功能尽可能透明。
  4. 如果你的管道创建了 中间工件 Intermediate Artifacts ,开发人员和 DevOps 人员可以使用这些工件来帮助调试问题,那么也要记录它的内容。是的,它会加长日志,但这只是文本。在某些时候,这会是有用的信息,而(利用得当的)日志不就是关于发生了什么和为什么发生的大量信息吗?

Kubernetes 机密信息:无法完全透明的地方

有些事情你不希望出现在日志里暴露出来。如果你在使用 Kubernetes 并引用保存在 Kubernetes 机密信息 Secrets 中的数据,那么你绝对不希望在日志中公开该数据,因为这些数据只是被混淆了,而没有被加密。

假如你想获取一些保存在机密信息中的数据,然后将其注入模板化 JSON 文件中。(机密信息和 JSON 模板的完整内容与此例无关。)按照最佳实践,你希望保持透明并记录你的操作,但你不想公开机密信息数据。

将脚本模式从调试(set -x)更改为命令记录(set -v)。在脚本敏感部分的结尾,将 Shell 重置为调试模式:

sh """
   # change script mode from debugging to command logging
   set +x -v

   # capture data from secret in shell variable
   MY_SECRET=\$(kubectl get secret my-secret --no-headers -o 'custom-column=:.data.my-secret-data')

   # replace template placeholder inline
   sed s/%TEMPLATE_PARAM%/${MY_SECRET_DATA}/ my-template-file.json

   # do something with modified template-file.json...

   # reset the shell to debugging mode
   set -x +v
"""

这将输出此行到日志:

sed s/%TEMPLATE_PARAM%/${MY_SECRET_DATA}/ my-template-file.json

与 Shell 调试模式中不同,这不会具现化 Shell 变量 MY_SECRET_DATA。显然,如果管道中在这一点出现问题,而你试图找出问题出在哪里,那么这不如调试模式有用。但这是在保持管道执行对开发人员和 DevOps 透明的同时,也保持你的秘密的最佳平衡。


via: https://opensource.com/article/21/5/jenkins-logs

作者:Evan “Hippy” Slatis 选题:lujun9972 译者:DCOLIVERSUN 校对:wxy

本文由 LCTT 原创编译,Linux中国 荣誉推出

相关内容

AI竟会「自己认错」?破解...
新智元报道 编辑:定慧 好困 【新智元导读】 在多智能体AI系统...
2025-06-02 21:12:04
SQL Server跟踪(...
写在前面的话: 该文章内容是参考   https:/...
2025-06-01 15:33:40
Jenkins--邮件通知...
1为啥要配置邮件通知配置邮件通知的目的是为了给用户发送构建结果的状...
2025-05-31 22:24:25
CentOS系统下wc命令...
CentOS中的文本统计利器:命令详解与应用 在CentOS系统的...
2025-05-29 06:11:07
shell命令或脚本 调用...
一、低版本Jenkins,或者不需要传递参数的job...
2025-05-28 12:06:29
如何在CentOS系统上部...
作为Linux系统中广泛使用的DNS服务软件,BIND(Berke...
2025-05-25 13:47:28

热门资讯

Helix:高级 Linux ... 说到 基于终端的文本编辑器,通常 Vim、Emacs 和 Nano 受到了关注。这并不意味着没有其他...
使用 KRAWL 扫描 Kub... 用 KRAWL 脚本来识别 Kubernetes Pod 和容器中的错误。当你使用 Kubernet...
JStock:Linux 上不... 如果你在股票市场做投资,那么你可能非常清楚投资组合管理计划有多重要。管理投资组合的目标是依据你能承受...
通过 SaltStack 管理... 我在搜索Puppet的替代品时,偶然间碰到了Salt。我喜欢puppet,但是我又爱上Salt了:)...
Epic 游戏商店现在可在 S... 现在可以在 Steam Deck 上运行 Epic 游戏商店了,几乎无懈可击! 但是,它是非官方的。...
《Apex 英雄》正式可在 S... 《Apex 英雄》现已通过 Steam Deck 验证,这使其成为支持 Linux 的顶级多人游戏之...
如何在 Github 上创建一... 学习如何复刻一个仓库,进行更改,并要求维护人员审查并合并它。你知道如何使用 git 了,你有一个 G...
2024 开年,LLUG 和你... Hi,Linuxer,2024 新年伊始,不知道你是否已经准备好迎接新的一年~ 2024 年,Lin...
什么是 KDE Connect... 什么是 KDE Connect?它的主要特性是什么?它应该如何安装?本文提供了基本的使用指南。科技日...
Opera 浏览器内置的 VP... 昨天我们报道过 Opera 浏览器内置了 VPN 服务,用户打开它可以防止他们的在线活动被窥视。不过...