首頁

目前文章總數:172 篇

  

最後更新:2025年 03月 22日

0017. 解決 Dotnet Build & MSBuild Jenkins 錯誤 error MSB4166: Child node exited prematurely. Shutting down

日期:2025年 02月 15日

標籤: Jenkins Continuous Integration(CI) Continuous Deployment(CD) Linux Ubuntu MSBuild DotNETSDK Asp.NET Framework

摘要:Jenkins


應用所需:1. jenkins 主機
解決問題:Jenkin CICD 部署時,發生錯誤 MSB4166: Child node exited prematurely. Shutting down 的解決方法
相關參考:StakeOverFlow討論
基本介紹:本篇分為3大部分。
第一部分:部署架構
第二部分:問題描述 & 原因
第三部分:解決方法 & Demo 結果






第一部分:部署架構

Step 1:部署架構

下圖是 Jenkins 進行 Docker 部署的簡易架構

階段 說明
1. Jenkins CI 1-1. 開始持續整合,首先拉取代碼
  1-2. 其次建立專案 & Publish 出部署檔案
  1-3. 最後封裝成 Docker Image
2. 上傳 Image 將 Jenkins 機器上建立的 Docker Image 上傳到 Harbar 或 DockerHub 上
3. 下載 Image 依照 Jenkins 上的 Pipeline 腳本,到指定的機器
4. Jenkins CD 4-1. 開始持續部署,被指定的機器會開始 拉取 Docker Image
  4-2. 執行 Docker Run 建立 Container 完成部署






第二部分:問題描述 & 原因

Step 1:問題

問題出現在 紅框 的地方




Step 2:造成原因 1 - 平行建置

微軟文檔關於 MSBuild 有提到
以下擷取關鍵一段:

根據同時執行建置的時間而定,移動或複製作業可能會因為檔案已存在於相同位置而失敗,
或者因為另一個 MSBuild 程序正在使用目的檔案而失敗。
此外,如果另一個 MSBuild 程序正在讀取或寫入相同檔案,則檔案讀取作業可能會失敗。


由此可知平行執行時,若另一個 Pipeline 要進行操作相同專案的 MSBuild 時就會出現此問題

Step 3:Jenkins 出現的錯誤描述

實際執行 Jenkins 時就會出現以下描述(如圖),某個子節點異常,強制中斷
就是因為要使用時 MSBuild 還未釋放資源,前一個 Job 尚在使用檔案


Step 4:Jenkins 出現的錯誤結構

以下狀況就是按下建置時發生的結果(如圖),第 1 個 Job 建置完成後,接續要更新第 2 個 Job 必定會造成異常
※由一個 Jenkins 主 Job Trigger 其他多個 Pipeline Job


Step 5:造成原因 2 - 硬體資源不足

如果在實務上,沒有發生這種狀況表示Jenkins CICD主機 記憶體、CPU 規格不錯,在 MSBuild 完成後,可以順利執行下一個工作
因此此問題通常出現在 忙碌 的 Jenkins 部署上、或者 配備規格低 的主機上
也就說明為何此問題不是每個 DevOps 人員都會遇到



第三部分:解決方法 & Demo 結果

Step 1:解決方法 - Dotnet Core

如果是 Asp.net Core 專案,在建置過程中,添加以下參數

--disable-build-servers 


完整範例(Ubuntu 上的 Shell 指令):

dotnet publish XXX.csproj -c Release -o publish/Output --disable-build-servers 



Step 2:解決方法 - .Net FramerWork

如果是 Asp.net Core 專案,在建置過程中,添加以下參數

-nodeReuse:false


完整範例(Ubuntu 上的 Shell 指令):

MSBuild XXX.csproj -t:Publish -p:Configuration=Release -p:OutputPath=publish/Output -nodeReuse:false



Step 3: Demo 結果

Demo 結果,基本上能順利執行每個 Stage
當添加這個方法後,每個 Job 都是獨立建置,執行速度會變慢,建議還是提高 CICD 機器的規格,成本實在不足再考慮用此方法解決