dlv支持debug、attach和exec三种方式。其中,attch方式类似于gdb -p <pid>,可以让调试器(dlv)挂接到已经在运行的进程上,然后进行调试。这个方式可用于分析和解决一些线上的疑难杂症,当然是否允许到生产上搞,那就case by case,大家自己把握吧……
本文假设远端和近端都装好了dlv,而且Visual Code的debug方案也已经添加完毕。相关的操作可以参考利用delve(dlv)在Visual Code中进行go程序的远程调试-debug方式的准备部分。
环境
- 近端
- Win7 64bit
- Visual Code 1.32.1 x64
- Go 1.10
- dlv 1.2
- 远端
- OpenSuSE 42.1
- Go 1.10
- dlv 1.2
- 示例项目
- hello/main.go,内容如下
package main
import (
"fmt"
"time"
)
const loopTimes = 60
func main() {
for i := 1; i < loopTimes; i++ {
time.Sleep(1 * time.Second)
fmt.Printf("\rLoop %v", i)
}
fmt.Println("")
}
准备01. 编译目标程序
就像javac和gcc一样,go编译器默认会在编译时,对最终的可执行代码执行面向机器的开发,而使得人类进行调试时不好理解。因此,如果在编译要被调试的目标程序时,最好禁用掉这些优化。Go 1.10及之后的版本,在编译时,加入-gcflags="all=-N -l"
选项;而之前的版本,则是加入-gcflags="-N -l"
选项。
在实例项目和环境中,我们用的是go 1.10,所以编译用的命令就变成这样了。
# 进入实例项目目录
cd $GOPATH/src/hello
# 执行编译任务
go build -gcflags="all=-N -l" hello
# 将编译好的程序拷贝到没有源代码的/tmp目录下,留作后面的步骤使用
mv hello /tmp
准备02. 启动目标程序
这次我们要做的是对“在运行程序”的远程调试工作,所以在调试开始之前,需要先把程序运行起来——但也就是单纯地按照程序的正常启动方法就行,不需要额外的参数或者调整。
/tmp/hello
执行方法
虽然不再需要代码,但与dlv debug一样,我们需要先在远端启动dlv的服务端。
dlv attach --headless --listen ":2345" --log --api-version 2 `pidof hello`
画面显示类似以下内容则说明dlv服务端已经就绪。
API server listening at: [::]:2345
INFO[0000] attaching to pid 3776 layer=debugger
和之前的dlv debug方式一样,回到Visual Code入debug界面,选择“Launch remote”方案后,点击启动来进行go debugger,就能启动远程调试了。
run_debug_in_VCode.gif总结
attach方式能应对的线上调试场景,也就只有它能够完成,是非常必不可少的。Visual Code+dlv能够正常支持attach方式,老衲甚为宽慰。但是有点非常要小心的地方,在Visual Code的debug控制栏里点击Stop按钮,会终结掉(可以理解为kill)你正在调试的目标程序。想要安全地关闭调试的话,目前最好的方法那就是在远端关闭掉dlv的服务端,比如直接在执行它的窗口里Ctrl+C或者另开一个对话去kill。
其实,对于dlv自己来说,它是能让用户选择退出调试后,是让目标程序继续跑下去,还是终结掉目标程序。按理来说,Visual Code应该会提供个配置项或者单独的按钮来做这个选择的。但目前我还没找着,如果找着了,我再更新吧。
网友评论