vscode 調試技巧|程序不是寫出來的?是調出來的!
常用的調試手段
作爲程序猿的我可太清楚調試的重要性了,有一句話說的很對:程序不是寫出來的,是調出來的。調試的方法很多,比如樸實的日誌打印,打點的計量統計(比如 golang 的 pprof 信息),還有無侵入式的單點調試。
在 c/c++ 我們最常用的是 gdb 調試,這是必備技能。在 golang 裏面,我經常用的是 dlv 調試,用來分析程序的底層邏輯。奇伢的調試姿勢通常有三種:
-
先 go build 編譯,出二進制文件,然後用 dlv exec 來調試;
-
程序已經跑在測試環境,dlv attach 調試;
-
程序出 core 了,dlv core 調試;
個人還是挺習慣這種較爲最原始的方式來調試程序。
避免依賴過重的工具?
IDE 提供了非常方便的調試功能,比如 goland 的調試功能,但 IDE 封裝的過於嚴重,並且調試界面的實現各有不同,雖然提供了便捷,但是它對程序猿幾乎相當於黑盒。一旦遇到點調試的問題,很難梳理清楚。並且當切換環境的時候經常要重新配置複雜的配置。
奇伢個人儘量強避免依賴這些 IDE 的特有的調試功能的,黑盒不透明是一個原因,第二個原因是類似 goland 這種商業付費的軟件,License 經常過期,在換電腦或平臺的時候,各種不同的付費策略導致這些軟件使用很糾結。並且太過依賴它,卻不知 dlv 通用的調試技能,會導致工具的遷移成本過高。
那奇伢是一定要沉浸在終端調試的美夢中嗎?
那不是,奇伢不排斥任何工具,只要你能完全掌控它即可。今天奇伢要分享一點關於 vscode 的調試姿勢,個人覺得是比較適合我的預期的:
-
很透明,讓用戶有種掌控的感覺;
-
姿勢通用,不會讓你只能依賴於 vscode ,還是 dlv 的用法;
-
工具全平臺可用,windows,mac,linux ,調試姿勢完全一樣;
vscode 只作爲一個界面,還是最基本的 gdb 或者 dlv 調試,這個過程讓你看得到。
奇伢的調試姿勢
Go 程序用的最多的還是 dlv 調試,現在有了 vscode ,感覺是有了一個新的體驗。本質上還是 dlv 調試。我們先捋一捋調試的思路,按照模式分爲兩大類來講:
-
調試二進制文件:先編譯,後調試,對應 launch 調試;
-
調試運行進程:調試正在運行的進程,對應 attach 調試;
如果按照代碼位置再區分 local 還是 remote ,那麼姿勢就可以分爲:
-
本地 launch 調試:vscode 在本機,代碼在本地,二進制在本地;
-
本地 attach 調試:vscode 在本機,代碼在本地,進程在本地;
-
遠程 lanuch 調試:vscode 在本機,代碼遠端,二進制在遠端;
-
遠程 attach 調試:vscode 在本機,代碼在本地,二進制在遠端;
下面分別舉兩個最典型的栗子,遠程開發 launch 調試和遠程 attach 調試,來看看奇伢是怎麼配置調試的吧。
1 遠程開發調試 launch
演示的場景:vscode 在本地,代碼在遠端,二進制在遠端。
這種方式本質是先編譯,後調試。先編譯出二進制文件,然後進行運行這個二進制文件進行調試。怎麼得到這個二進制?
有兩種方式:
-
讓 vscode 編譯出你的二進制文件,通過配置 task.json 這個文件,定義你的編譯規則;
-
還有一種方式,就是純粹靠你自己來編譯出二進制,比如你寫了個 Makefile 或者 go build 出你的二進制;
只要有個二進制,我們就能調試。這個對應了我常用的 dlv exec 的方式。vscode 調試首先創建一個 .vscode/launch.json 的配置文件:
{
// 自定義名字
"name": "Launch file",
// 調試的程序類型
"type": "go",
// 調試類型(調試二進制)
"request": "launch",
// 調試類型
"mode": "debug",
// 調試的程序
"program": "${file}"
}
上面的配置好後,打開你的主程序( main.go )文件,給你的文件設置個斷點,點擊左側的運行調試按鈕。就能讓 vscode 先編譯,後調試,並且停頓再斷點出。
vscode 會編譯出一個二進制文件 __debug_binxxx ,然後 debug 這個文件,並且 dlv dap 也會啓動一個 dap server,用於和 vscode 鏈接
示例如圖:
這個太簡單了,幾乎沒有任何障礙。
2 遠程調試 attach
演示的場景:vscode 在本地,代碼在本地,進程在遠端。 這種場景說白了就是:我代碼在本地,進程在線上。
因爲奇伢是做後端開發的,平時開發的程序都是守護進程,那麼 attach 這種方式是更通用的方式。往往就是進程正在運行,我們再去調試。gdb 和 dlv 都具備 attach 這種能力。這種場景,是經常在調試線上的守護程序來的。
如果是本地終端用這種方式調試:
dvl attach <pid>
假設,當前我們進程跑在線上:
-
在某臺測試機器上,程序已經跑起來了,機器上沒有代碼;
-
我們本地有版本一致的代碼,用 vscode 打開着;
你想要調試它,怎麼辦?
第一種方法:可以 ssh 到遠端機器,然後 dlv 去調試。對比着本地的代碼設置斷點,進行調試。相對來講比較麻煩。
假設,如果能用本地的代碼加上遠端的 dlv ,無縫聯合起來,同步調試?豈不是完美。
vscode 支持這種方式! 使用的是 dlv 的 dap 功能,遠端機器上用 dlv attach 到對應進程,且開一個 dap server 監聽端口,本地 vscode 去連接這個端口。它們之間的通信使用 DAP 協議走網絡傳輸,從而實現遠程的 attach 調試。
下面來看一下具體演示步驟吧。
1 步驟一:遠程拉起進程
這個很簡單,後端開發,守護進程纔是最常見的場景。
# 自己的進程自己拉。假設進程號是 7488
./hello_server
2 步驟二:dlv dap 服務器
開啓一個 dap 服務器,並且 dlv attach 到對應的進程上,並啓動 dap 服務器;
dlv --headless -l 0.0.0.0:2345 attach 7488 --api-version 2
解釋:
-
7488 是 hello_server 的進程號
-
dlv 其實隨便在哪個目錄執行都可以
-
注意聲明 --api-version 2
3 步驟三:vscode 客戶端配置
這個作爲 dap 客戶端,配置和 dlv dap 服務器的聯通即可。
"configurations": [
{
// 自定義,名字,看起來有意義就行,用來給你選的;
"name": "Connect to server",
// 調試的是 go 程序
"type": "go",
// attach 進程的方式
"request": "attach",
// 遠程調試
"mode": "remote",
// 注意!!非常關鍵,這是能否成功設置斷點的關鍵參數。
"remotePath": "{編譯的項目路徑}",
// dlv server 啓動的端口
"port": 2345,
// 遠程主機的 IP
"host": "192.168.56.12"
}
]
強調 remotePath 這個參數,這個參數非常關鍵,是你能否遠程斷點成功的關鍵。它並不是進程當前的目錄,也不是本地項目的代碼目錄,而是編譯二進制的項目目錄。
舉個栗子:加入 hello_server 這個進程是在 /root/code/ 這個目錄編譯的,那麼 remotePath 目錄填的這個。後面 hello_server 放到其他任意目錄運行都和 remotePath 沒關係。
4 步驟四:運行調試
設置斷點,發一個請求,就可以調試了。演示效果:
斷點技巧
vscode 能打的斷點有三種:
-
普通斷點,運行到了就會停住;
-
條件斷點,滿足條件纔會停住;
-
日誌斷點,運行到了只打印,不停;
1 Breakpoint
普通斷點,這是最常見的斷點,提前設置到代碼某個位置,運行到了就會停在對應位置。
2 Conditional Breakpoint
條件斷點。滿足條件纔會斷住,這個可以更精準的調試。這個表達式是語言本身的表達式即可:比如 c++ :
tag == 2
tag 是 c++ 的一個整形變量。
3 Logpoint
日誌打印,不斷點。很實用的技巧,只要路過就會打印一行信息。適用於不適合暫停調試的程序。比如可以輸入:
result is {result.code()}
result 是 c++ 的一個 class 變量,code 是它的方法。
Debug Console
程序斷點打住之後,我們還可以交互(就和 gdb,dlv 一樣,手動輸入命令),可以輸入命令前綴 -exec
。比如,反彙編:
-exec disassemble
打印寄存器:
-exec print $rip
想知道全部命令,可以 help 一下:
-exec help
總結
-
調試的兩大類 launch 調試和 attach 調試,開發過程 launch 模式可能佔多數,但是測試過程,attach 模式可能纔是多數的需求;
-
使用 dlv dap 開啓一個 dap server,這樣讓編輯器或者 IDE 都能夠通過網絡介入調試;
-
vscode 調試只是作爲一個客戶端,代碼在本地,程序在遠端,用 vscode 拉通起來,完美體驗;
-
遠程 attach 調試其實不需要遠端有代碼哦,這個記住了,remotePath 參數是關鍵;
-
除了普通斷點,條件斷點和日誌斷點真的挺有用的;
後記
學會調試,程序學習上手就快,高效的工具纔是生產力。點贊、在看 是對奇伢最大的支持。
奇伢雲存儲 雲存儲深耕之路,專注於對象存儲,塊存儲,雲計算領域。堅持撰寫有思考的技術文章。
本文由 Readfog 進行 AMP 轉碼,版權歸原作者所有。
來源:https://mp.weixin.qq.com/s/6JKIkTJn28cG66Slwv_TIA