Go 语言调试工具 —dlv
本文记录下dlv 安装和使用记录。
安装
下载 和编译delve 分支
$ git clone https://github.com/go-delve/delve$ cd delve$ go install github.com/go-delve/delve/cmd/dlv
Go versin 1.16版本和之后的版本 可以直接使用
$ go install github.com/go-delve/delve/cmd/dlv@latest
dlv 安装到$GOPATH/bin目录下,可以执行执行dlv命令查看是否安装成功.
[lituanjie@localhost src]$ dlv helpDelve is a source level debugger for Go programs.Delve enables you to interact with your program by controlling the execution of the process,evaluating variables, and providing information of thread / goroutine state, CPU register state and more.......
如何调试的程序
dlv attach
dlv 使用attach 命令调试运行的程序,先使用ps -aux | grep pid-name 找到程序的pid号,在执行dlv attach pid-num
[lituanjie@localhost ~]$ ps -aux | grep dlv_testlituanj+ 30992 0.0 0.0 702960 6956 pts/3 Sl+ 16:17 0:00 ./dlv_testlituanj+ 31282 0.0 0.0 112812 976 pts/1 S+ 16:19 0:00 grep --color=auto dlv_test[lituanjie@localhost ~]$[lituanjie@localhost ~]$ dlv attach 30992Type 'help' for list of commands.(dlv)(dlv)
dlv debug
使用dlv debug 会编译并调试当前目录下的程序,也可以指定package的位置
[lituanjie@localhost dlv_test]$ dlv debugType 'help' for list of commands.(dlv) break main.mainBreakpoint 1 (enabled) set at 0x4b8918 for main.main() ./main.go:8(dlv) c> main.main() ./main.go:8 (hits goroutine(1):1 total:1) (PC: 0x4b8918)3: import (4: "fmt"5: "time"6: )7:=> 8: func main() {9: fmt.Println("dlv test")10: for {11: time.Sleep(2 * time.Second)12: fmt.Println("dlv test")13: }(dlv) n
也可制定package
[lituanjie@localhost src]$ dlv debug github.com/dlv_test/
dlv exec
dlv exec 是调试已经编译好的程序
[lituanjie@localhost dlv_test]$ go build main.go[lituanjie@localhost dlv_test]$ lsmain main.go[lituanjie@localhost dlv_test]$ dlv exec ./mainType 'help' for list of commands.(dlv) b main.mainBreakpoint 1 (enabled) set at 0x4992f3 for main.main() ./main.go:8(dlv) n> main.main() ./main.go:8 (hits goroutine(1):1 total:1) (PC: 0x4992f3)Warning: debugging optimized function3: import (4: "fmt"5: "time"6: )7:=> 8: func main() {9: fmt.Println("dlv test")10: for {11: time.Sleep(2 * time.Second)12: fmt.Println("dlv test")13: }(dlv)
dlv core
使用dlv core 可以core文件
远程调试
go 语言支持远程调试,在程序运行的机器上开启dlv server, 在代码编译机上开启dlv client,可以方便调试。
--headless Run debug server only, in headless mode.
这个命令适合 attach, debug, test …等调试,在调试的时候加上—headless选项就可以。
dlv [exec | attach | debug | test ...] --headless --listen ip:portnum 进程
dlv server
ubuntu@ubuntu:~$ dlv exec --headless --listen :3000 ./mainAPI server listening at: [::]:3000
dlv client
#172.16.0.22 是server的IP地址[lituanjie@localhost ~]$ dlv connect 172.16.0.22:3000Type 'help' for list of commands.(dlv) b main.mainBreakpoint 1 (enabled) set at 0x4992f3 for main.main() ./workspace/newgitlab/gowork/src/github.com/dlv_test/main.go:8(dlv) c> main.main() ./workspace/newgitlab/gowork/src/github.com/dlv_test/main.go:8 (hits goroutine(1):1 total:1) (PC: 0x4992f3)Warning: debugging optimized function3: import (4: "fmt"5: "time"6: )7:=> 8: func main() {9: fmt.Println("dlv test")10: for {11: time.Sleep(2 * time.Second)12: fmt.Println("dlv test")13: }(dlv)
go 编译的程序是优化之后的程序,在调试中会出现信息不全的情况,最好在编译时加上gcflags='all=-N -l'
go build -gcflags='all=-N -l' main.go
常用的命令
| Command | Descripton | usage |
|---|---|---|
| call | 调用函数 | call [-unsafe] |
| continue | 继续执行直到指定断点或程序结束 | continue [] |
| next | 执行下一步 | next [count] |
| step | 进入函数 | |
| stepout | 退出当前函数 | |
| break | 设置断点 | break [name] |
| breakpoints (bp) | 打印所有断点 | |
| condition | 设置有条件的断点 | condition . |
| clear | 清除断点 | clear |
| clearall | 清除所有断点 | clearall [] |
| display | 程序每次停止时打印变量 | display -a [%format] display -d -a选项是添加一个表达式 -b删除一个表达式 |
| 打印变量 | [goroutine ] [frame ] print [%format] | |
| regs | 打印CPU registers的内容 | |
| goroutine | 显示或这个改变当前的goroutine | goroutine goroutine goroutine |
| goroutines | 列出所有的goroutine | goroutines [-u (default: user location)|-r (runtime location)|-g (go statement location)|-s (start location)] [-t (stack trace)] [-l (labels)] -u displays location of topmost stackframe in user code -r displays location of topmost stackframe (including frames inside private runtime functions) -g displays location of go instruction that created the goroutine -s displays location of the start function -t displays goroutine’s stacktrace -l displays goroutine’s labels |
| thread | 切换指定的thread | |
| threads | 打印所有的thread | |
| stack | 打印堆栈的信息 | |
| frame | 设置当前的frame, 或者在不同的frame执行命令 | frame frame |
| list | 显示代码 | [goroutine ] [frame ] list [] frame 1 list 69 list testvariables.go:10000 list main.main:30 list 40 |
| set | 改变变量的值 | [goroutine ] [frame ] set = |
| whatis | 打印变量的类型 | whatis |
常用指定断点方式
*<address>Specifies the location of memory address address. address can be specified as a decimal, hexadecimal or octal number<filename>:<line>Specifies the line line in filename. filename can be the partial path to a file or even just the base name as long as the expression remains unambiguous.<line>Specifies the line line in the current file+<offset>Specifies the line offset lines after the current one-<offset>Specifies the line offset lines before the current one<function>[:<line>]Specifies the line line inside function. The full syntax for function is<package>.(*<receiver type>).<function name>however the only required element is the function name, everything else can be omitted as long as the expression remains unambiguous. For setting a breakpoint on an init function (ex: main.init), the<filename>:<line>syntax should be used to break in the correct init function at the correct location./<regex>/Specifies the location of all the functions matching regex
