如何使 Jenkins 日誌更可讀
Jenkins 是一個自由開源的自動化伺服器,用於構建、測試和部署代碼。它是 持續集成 (CI)、 持續交付 (CD)的基礎,可以為開發人員每天節約幾小時,並保護他們免受失敗的代碼上線的影響。一旦代碼失效或開發人員需要查看測試輸出時,Jenkins 提供了日誌文件以供檢查。
默認的 Jenkins 管道 日誌可能難以閱讀。這篇關於 Jenkins 日誌的基礎知識的總結文章提供了一些技巧(和代碼),說明了如何提升它們的可讀性。
你獲得什麼
Jenkins 管道分為 幾個階段。Jenkins 自動記錄每個階段的開始,記錄內容如下:
[Pipeline] // stage
[Pipeline] stage (hide)
[Pipeline] { (Apply all openshift resources)
[Pipeline] dir
上文顯示的內容沒有太大區分度,重要的內容(如階段的開始)未突出顯示。在多達數百行的管道日誌中,要找到一個階段的起始和另外一個階段的終止位置可能會很艱巨。當隨意瀏覽日誌尋找一個特定的階段的時候,這種艱巨尤其明顯。
Jenkins 管道是由 Groovy 和 Shell 腳本混合編寫的。在 Groovy 代碼中,日誌記錄很少。很多時候,日誌是由命令中的不起眼的文本組成,沒有詳細信息。在 Shell 腳本中,打開了調試模式(set -x
),所以每條命令都會被完全 具現化 (變數被解除引用並列印出數值)並詳細記錄,輸出也是如此。
鑒於日誌可能有很多內容,通讀日誌獲取相關信息可能很繁瑣。由於在管道中被處理,並跟著一個 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
方法以相同的方式工作,但是它會立即使腳本失效。這有助於突顯失敗的位置與原因。
最佳實踐
- 在你的 Groovy 代碼中大量使用
echo
Jenkins 步驟來通知用戶你在做什麼。這些也可以幫助記錄你的代碼。 - 使用空的日誌語句(Groovy 中空的 echo 步驟、
echo ''
或 Shell 中的echo
)來分割輸出,提高可讀性。你可能在你的代碼中為同樣的目的使用空行。 - 避免在腳本中使用
set +x
的陷阱,因為它隱藏了日誌記錄已執行的 Shell 語句。它並沒有清理你的日誌,而是使你的管道成為一個黑盒子,隱藏了管道正在做的行為以及出現的任何錯誤。確保管道功能儘可能透明。 - 如果你的管道創建了 中間工件 ,開發人員和 DevOps 人員可以使用這些工件來幫助調試問題,那麼也要記錄它的內容。是的,它會加長日誌,但這只是文本。在某些時候,這會是有用的信息,而(利用得當的)日誌不就是關於發生了什麼和為什麼發生的大量信息嗎?
Kubernetes 機密信息:無法完全透明的地方
有些事情你不希望出現在日誌里暴露出來。如果你在使用 Kubernetes 並引用保存在 Kubernetes 機密信息 中的數據,那麼你絕對不希望在日誌中公開該數據,因為這些數據只是被混淆了,而沒有被加密。
假如你想獲取一些保存在機密信息中的數據,然後將其注入模板化 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
本文轉載來自 Linux 中國: https://github.com/Linux-CN/archive