[工作經驗] 為了一個句點 debug 了三小時

有沒有什麼 bug 讓你 debug 了超級久,結果卻發現只是一兩個字的差異? 我們應該都有類似的經驗,可能是打錯字,或是複製貼上卻忘了改一個東西。這次我遇到的 bug 只是一個句點之差,就一個句點!

這次的問題是由 Python script 去執行 LSF job,做的事非常簡單,就是執行一個 "test.sh" 而已。但在 LSF 卻會遇到錯誤,看了 log 卻久久不能明白為什麼:


bash: test.sh: command not found

但這個檔案 test.sh 如果我直接在 terminal 執行根本沒有問題,權限也有設定可以 chmod +x 可以直接執行。

更讓人覺得詭異的是,如果我直接把一樣的指令從 terminal 執行 bsub 出去,就不會有問題,但從 Python script 執行就有問題。

Debug 過程

因為這個檔案是動態建立出來再執行的,一開始以為是不是建立的時間太晚,那我們把動態建立關掉,讓這個檔案從頭到尾都存在,發現還是一樣的問題。

那既然檔案都在,是不是 LSF 那邊硬碟之類的有問題? 或是 current working directory 沒有設定好? 在跑 test.sh 之前先用 ls 看一下目前資料夾的檔案,結果 test.sh 有顯示,而且模式也有 +x 可以執行。

感覺越來越奇妙了,檔案明明就在,你為什麼就不給我執行? 通常在不同 shell 環境下,我們也只能懷疑是不是 environment variables 造成什麼影響,所以我就用了一個 "env | sort" 指令觀察一下 Python 執行的 bsub 與自己手動跑 bsub 的 LSF 環境下到底有什麼差異。

沒想到還真的找到了不一樣的地方。我發現手動執行 bsub 的環境的 $PATH 變數多了一個 "." 但 Python script 執行的卻沒有,這時才突然恍然大悟,原來錯誤訊息抱怨的是 "command not found" 並不是抱怨檔案找不到。當我們用 "test.sh" 去執行,並不是用 "./test.sh" 執行的話,Linux 會找所有的 $PATH 來找可以執行的 binary,因為 "." 代表的是當前的資料夾,因此手動執行的環境才沒有問題。

但這個 Python script 已經行之有年,為什麼其他同事沒遇到錯誤,就只有我? 原來是因為我習慣用 bash,但公司預設用 tcsh 而且預設的 tcsh startup file .cshrc 就有加 "." 到 $PATH。但我在 .bashrc 設定 $PATH 的時候剛好就忘記加到了 ".",然後 Python script 執行的環境下有可能因為一些 interactive/non-interactive/login/non-login shell 的關係導致 .bashrc 被執行,因此會使用到我沒有加 "." 的 $PATH,才出現這樣的問題。

該修正的方向

好的程式應該要不受使用者環境影響才對,所以後來我們的解法就是用 "./test.sh" 或是 "bash test.sh" 方式來執行 script,就不會再受到 $PATH 的影響了。

這也告訴我們,有時候該懷疑的不是別人的 code,而是自己的環境是不是沒設定好。還有 "env | sort" 是一個非常好用的技巧,之前在 GitLab pipeline 也是用同樣的技巧在未知的環境下釐清問題。

留言

此網誌的熱門文章

[試算表] 追蹤台股 Google Spreadsheet (未實現損益/已實現損益)

[Side Project] 互動式教學神經網路反向傳播 Interactive Computational Graph

[插件] 在 Chrome 網頁做區分大小寫的搜尋