Bash是在 Unix 和 Unix-like OS上主要的 Shell,由於特定原因,我必須在一個部署於K8s Pod內的.NET程式呼叫一個寫好的Bash,由Bash做一些事情,而這個Bash檔是直接包進Container內的。起初在本機開發測試時一切正常,然而經由Azure DevOps CI/CD後卻發生"/bin/bash^M: bad interpreter: No such file or directory"異常。
首先環境上在本機開發階段,是透過WSL環境打包Container Image,而測試也是Ubuntu環境,並且由於是要執行 Bash,因此在撰寫 Bash 時必須要特別注意換行符號,因為Linux 和 Windows 所使用的換行字元是不一樣,在 Linux 使用\n 表示換行,而 Windows 使用 \r\n 表示換行,這個小細節會影響到 Bash 在Linux是否能被正確解讀,所以在開發上可以使用 Visual Studio Code 來處理這個問題,只要切換成 LF 模式就可以。
接著經由Azure DevOps CI/CD後,在測試環境卻發生了異常,而這個異常表明是 Bash 內容有問題"/bin/bash^M: bad interpreter: No such file or directory",然而在前面已提到過,在撰寫Bash已特別注意換行符號,理應不會有這個問題才對,且本機開發測試均正常(對,就是工程師名言:在我的電腦是好的),莫非在CI/CD中發生什麼事?
在CI程序中主要是Build & UnitTest APP,在CD程序中,做打包Container Image以及Deploy 作業,由於一開始是走Windows Container,因此負責CI/CD的Pipeline agent清一色都是Windows,而後來因為Windows Container 實在太多毛了(這又是另一番血淚史),故轉為使用Linux Container +K8s,這個階段由於程式都是.NET Core,且在CI並不打包Container Image,因此延用原本的agent(windows OS),只有CD的部份改換Ubuntu,沒想到,就是這個混合模式導致了本次異常的現象。
程式的版控我們採用Azure DevOps Git Repo,所以在 CI agent 在build app過程中會有git Clone的動作取得程式源碼,再進行build & UnitTest作業,而agent是windows OS,因此懷疑在這個Clone 過程,Bash 檔在複製時,產生了被修改的行為,導致了換行符號被置換為\r\n ,然後在CD打包Container Image,Deploy到測試環境後,導致這個Bash 檔在執行時就引發了"/bin/bash^M: bad interpreter: No such file or directory"異常。
為了證實,因此把CI agent改為Ubuntu OS,然後...啪一下....Bash 檔在執行時就正常囉,所以還是一條龍服務比較沒有雷(別混用Windows+Linux CI/CD)。
By No.18