使用GDB或Delve对已经运行起来的Go程序进行远程调试

同步发布在我的博客,欢迎来点赞。
使用 GDB 或 Delve 对已经运行起来的 Go 程序进行远程调试

使用 GDB 或 Delve 对已经运行起来的 Go 程序进行远程调试

背景

Java 程序可以很方便地通过 jdwp 参数指定一个对外端口进行远程调试,如

java \
-agentlib:jdwp=transport=dt_socket,server=y,suspend=n,address=50055 \
-jar remote-debug-0.0.1-SNAPSHOT.jar &

这样,我们在本地机器就可以很方便地调试远程已经运行起来的 Java 程序了。

那么,Golang 是否有类似的方法能实现呢?

GDB

通过以下指令安装

apt install gdbserver  #  在远程机器上
apt install gdb  # 在本地机器上

1. 启动 Go 程序

假设我们有一个http 服务端程序:

package mainimport ("fmt""log""net/http""strings"
)func sayHelloName(w http.ResponseWriter, r *http.Request) {fmt.Println()_ = r.ParseForm() //解析参数,默认是不会解析的fmt.Println(r.Form)fmt.Println("path", r.URL.Path)fmt.Println("scheme", r.URL.Scheme)fmt.Println(r.Form["url_long"])for k, v := range r.Form {fmt.Println("key", k)fmt.Println("val", strings.Join(v, ""))}fmt.Fprintf(w, "Hello astaxie!")
}func main() {http.HandleFunc("/", sayHelloName)// 使用默认路由器开始监听err := http.ListenAndServe(":9090", nil)if err != nil {log.Fatal("ListenAndServe: ", err)}
}

将其编译并运行:

go build -o main
./main

这样,此时,这个简单的go程序就开始运行了。

2. 使用 gdbserver 连接程序

另起一个终端,使用 gdbserver 连接这个进程

## 获取进程pid
# ps aut | grep main   
root      3664  0.0  0.0 1600584 6012 pts/1    Sl+  12:38   0:00 ./main
## 连接到这个进程,<2345>是自行指定的对外端口
# gdbserver localhost:2345 --attach 3664
Attached; pid = 3664
Listening on port 2345

这样,我们的开发机就准备好远程调试我们的go程序了。

顺便,第1、2步可以直接使用gdbserver指令代替:

gdbserver localhost:2345 ./main

3. 使用 gdb 连接到 gdbserver

在本地的机器上使用 gdb 连接启动的 gdbserver 服务。这里在同一台机器(localhost)上模拟

# gdb  # 运行gdb    
GNU gdb (Ubuntu 12.1-0ubuntu1~22.04.3) 12.1
Copyright (C) 2022 Free Software Foundation, Inc.
License GPLv3+: GNU GPL version 3 or later <http://gnu.org/licenses/gpl.html>
This is free software: you are free to change and redistribute it.
There is NO WARRANTY, to the extent permitted by law.
Type "show copying" and "show warranty" for details.
This GDB was configured as "x86_64-linux-gnu".
Type "show configuration" for configuration details.
For bug reporting instructions, please see:
<https://www.gnu.org/software/gdb/bugs/>.
Find the GDB manual and other documentation resources online at:<http://www.gnu.org/software/gdb/documentation/>.For help, type "help".
Type "apropos word" to search for commands related to "word".
(gdb) target remote localhost:2345  
Remote debugging using localhost:2345
Reading /root/project/go-web/main from remote target...
warning: File transfers from remote targets can be slow. Use "set sysroot" to access files locally instead.
Reading /root/project/go-web/main from remote target...
Reading symbols from target:/root/project/go-web/main...
Reading /lib/x86_64-linux-gnu/libc.so.6 from remote target...
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading symbols from target:/lib/x86_64-linux-gnu/libc.so.6...
Reading symbols from /usr/lib/debug/.build-id/49/0fef8403240c91833978d494d39e537409b92e.debug...
Reading symbols from target:/lib64/ld-linux-x86-64.so.2...
Reading symbols from /usr/lib/debug/.build-id/41/86944c50f8a32b47d74931e3f512b811813b64.debug...
Reading /lib64/ld-linux-x86-64.so.2 from remote target...
Reading /usr/lib/debug/.build-id/04/f611a778dee3b5f92c1df94f899d200c106375.debug from remote target...
internal/runtime/syscall.Syscall6 () at /usr/local/go/src/internal/runtime/syscall/asm_linux_amd64.s:36
36              CMPQ    AX, $0xfffffffffffff001
(gdb) list
31              MOVQ    DI, DX  // a3
32              MOVQ    CX, SI  // a2
33              MOVQ    BX, DI  // a1
34              // num already in AX.
35              SYSCALL
36              CMPQ    AX, $0xfffffffffffff001
37              JLS     ok
38              NEGQ    AX
39              MOVQ    AX, CX  // errno
40              MOVQ    $-1, AX // r1
(gdb) 

使用 gdb 指令target remote指定远程gdbserver的地址即可。

Delve

gdb只能看到对应的汇编代码(想查看源代码可能需要更多设置),而且常用的 IDE Goland 并不支持 GDB 调试 Go 程序。

更好的解决办法是使用 Delve 构建。

在远程机器上安装:

apt install delve

如果在之后的第二步运行时报错:

# dlv attach 5600 --headless --listen=:2345 --api-version=2 --log
API server listening at: [::]:2345
2024-11-18T12:57:43+08:00 warning layer=rpc Listening for remote connections (connections are not authenticated nor encrypted)
2024-11-18T12:57:43+08:00 info layer=debugger attaching to pid 5600
2024-11-18T12:57:43+08:00 error layer=debugger can't find build-id note on binary
2024-11-18T12:57:44+08:00 error layer=debugger could not patch runtime.mallogc: no type entry found, use 'types' for a list of valid types
panic: <nil> not an Intgoroutine 1 [running]:
go/constant.Int64Val({0x0, 0x0})go/constant/value.go:502 +0x119
github.com/go-delve/delve/pkg/proc.(*Variable).parseG.func2({0xa580c0, 0xc000a41e48})github.com/go-delve/delve/pkg/proc/variables.go:879 +0x49
github.com/go-delve/delve/pkg/proc.(*Variable).parseG(0xb3a588)github.com/go-delve/delve/pkg/proc/variables.go:901 +0x5b5
github.com/go-delve/delve/pkg/proc.GetG({0xb3a588, 0xc00035c460})github.com/go-delve/delve/pkg/proc/variables.go:258 +0xae
github.com/go-delve/delve/pkg/proc.NewTarget({0xb3e4e0, 0xc0001b4480}, 0x15e0, {0xb3a588, 0xc00035c460}, {{0xc000288050, 0xe}, {0xc0001d5110, 0x1, 0x1}, ...})github.com/go-delve/delve/pkg/proc/target.go:210 +0x2cf
github.com/go-delve/delve/pkg/proc/native.(*nativeProcess).initialize(0xc0001b4480, {0xc000288050, 0xe}, {0xc0001d5110, 0x1, 0x1})github.com/go-delve/delve/pkg/proc/native/proc.go:268 +0x145
github.com/go-delve/delve/pkg/proc/native.Attach(0x5a3725, {0xc0001d5110, 0x1, 0x1})github.com/go-delve/delve/pkg/proc/native/proc_linux.go:157 +0x18f
github.com/go-delve/delve/service/debugger.(*Debugger).Attach(0xc00035c230, 0xc000000004, {0x0, 0x5})github.com/go-delve/delve/service/debugger/debugger.go:349 +0xd6
github.com/go-delve/delve/service/debugger.New(0xc0001ce1c0, {0xc00014c970, 0x0, 0x4})github.com/go-delve/delve/service/debugger/debugger.go:160 +0x5c5
github.com/go-delve/delve/service/rpccommon.(*ServerImpl).Run(0xc000125260)github.com/go-delve/delve/service/rpccommon/server.go:122 +0xd6
github.com/go-delve/delve/cmd/dlv/cmds.execute(0x15e0, {0xc00014c970, 0x0, 0x4}, 0xc0001d8ea0, {0x0, 0x0}, 0x3, {0xc00014c960, 0x1, ...}, ...)github.com/go-delve/delve/cmd/dlv/cmds/commands.go:971 +0xc7f
github.com/go-delve/delve/cmd/dlv/cmds.attachCmd(0xc0001eaf00, {0xc00014c960, 0x1, 0x5})github.com/go-delve/delve/cmd/dlv/cmds/commands.go:771 +0x145
github.com/spf13/cobra.(*Command).execute(0xc0001eaf00, {0xc00014c910, 0x5, 0x5})github.com/spf13/cobra/command.go:860 +0x5f8
github.com/spf13/cobra.(*Command).ExecuteC(0xc0001eac80)github.com/spf13/cobra/command.go:974 +0x3bc
github.com/spf13/cobra.(*Command).Execute(...)github.com/spf13/cobra/command.go:902
main.main()github.com/go-delve/delve/cmd/dlv/main.go:24 +0x18a

这可能是Delve版本不匹配,可以改用以下方法安装:

go install github.com/go-delve/delve/cmd/dlv@latest

1. 编译并运行 Go 程序

同样地,我们使用之前的 http 服务作为例子。

go build 的参数all=-N -l表示关闭优化和内联,这会让调试更加准确。

go build -gcflags="all=-N -l" -o main
./main

2. 使用 delve 连接运行中的进程

和 gdbserver 操作类似,需要指定进程 pid 和对外端口。

# ps aux | grep main 
root      7799  0.0  0.0 1602348 10320 pts/1   tl+  13:03   0:00 ./main
# dlv attach 7799 --headless --listen=:2345 --api-version=2 --log 

3. 在本地机器连接到远程的 Delve 服务器

这里直接使用 Goland 内置的 Delve 工具

创建一个 Go Remote 的配置

在这里插入图片描述

指定远程 delve 服务的 ip 和端口

在这里插入图片描述

配置完成,启动调试,就会在我们预设的断点处停止了。

在这里插入图片描述

如同在本地一般,我们可以查看变量并对其进行调试:

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/475450.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

如何解决pdf.js跨域从url动态加载pdf文档

摘要 当我们想用PDF.js从URL加载文档时&#xff0c;将会因遇到跨域问题而中断&#xff0c;且是因为会触发了PDF.js和浏览器的双重CORS block&#xff0c;这篇文章将会介绍&#xff1a;①如何禁用pdf.js的跨域&#xff1f;②如何绕过浏览器的CORS加载URL文件&#xff1f;②如何使…

Jmeter中的断言(三)

9--MD5Hex断言 功能特点 数据完整性验证&#xff1a;验证响应数据的 MD5 哈希值是否符合预期。简单配置&#xff1a;只需提供预期的 MD5 哈希值即可。灵活配置&#xff1a;可以设置多个断言条件&#xff0c;满足复杂的测试需求。 配置步骤 添加 MD5Hex 断言 右键点击需要添加…

Tomcat和Nginx原理说明

Tomcat Tomcat 是一个开源的 Java 应用服务器&#xff0c;它由多个关键组件组成。这些组件共同协作&#xff0c;实现了 Servlet 容器的功能。以下是 Tomcat 的核心组件说明及其逻辑架构的示意图。 1. Tomcat 核心组件说明 (1) Server 描述&#xff1a;Tomcat 的顶级组件&…

vmWare虚拟环境centos7安装Hadoop 伪分布式实践

背景&#xff1a;近期在研发大数据中台&#xff0c;需要研究Hadoop hive 的各种特性&#xff0c;需要搭建一个Hadoop的虚拟环境&#xff0c;本来想着使用dock &#xff0c;但突然发现docker 公共仓库的镜像 被XX 了&#xff0c;无奈重新使用vm 搭建虚拟机。 大概经历了6个小时完…

10 基于深度学习的目标检测

首次完成时间&#xff1a;2024 年 11月 20 日 1. 使用OpenCV的dnn模块实现图像分类。 1&#xff09;程序代码&#xff1a; import numpy as np import cv2# 解析标签文件 row open("model1/synset_words.txt").read().strip().split("\n") class_label …

ssl证书,以 Nginx 为例

文章目录 1 证书概述1.1 常见证书格式1.2 证书的几种扩展名1.3 关于 PKCS#12 格式 2 Nginx 下证书配置2.1 证书的工作原理2.1.1 单向认证2.1.2 双向认证 2.2 CA 机构签发2.2.1 免费 SSL 证书申请2.2.2 双向认证 2.3 自签证书2.3.1 单向认证2.3.2 双向认证 附录 1&#xff1a;Wi…

android:taskAffinity 对Activity退出时跳转的影响

android:taskAffinity 对Activity跳转的影响 概述taskAffinity 的工作机制taskAffinity对 Activity 跳转的影响一个实际的开发问题总结参考 概述 在 Android 开发中&#xff0c;任务栈&#xff08;Task&#xff09;是一个核心概念。它决定了应用程序的 Activity 如何相互交互以…

专家PID控制

专家PID控制&#xff08;Expert PID Control&#xff09;是一种结合了传统PID控制和专家系统思想的控制方法。它通过引入专家经验、规则和推理机制&#xff0c;以改善PID控制器在面对复杂系统时的性能。专家PID控制不仅仅依赖于固定的PID参数&#xff08;比例、积分、微分&…

ES分词环境实战

文章目录 安装下载1.1 下载镜像1.2 单节点启动 防火墙设置异常处理【1】iptable链路中断 参考文档 参加完2024年11月软考&#xff0c;对ES的分词进行考查&#xff0c;前期有【 Docker 环境下安装部署 Elasticsearch 和 kibana】和【 Docker 环境下为 Elasticsearch 安装IK 分…

【桌面应用程序】Vue-Electron 环境构建、打包与测试(Windows)

前言 Vue 与 Electron 环境构建、打包与测试。 目录 前言 一、基本环境准备 二、配置npm源 三、创建Vue项目 四、添加Electron支持 五、应用启动 ​六、添加UI框架 ElementUI ​七、打包 一、基本环境准备 npm版本&#xff1a;8.6.0node版本&#xff1a;v18.0.0Vue/…

golang中的init函数

程序的初始化和执行都起始于 main 包。如果 main 包还导入了其它的包&#xff0c;那么就会在编译时将它们依次 导入。有时一个包会被多个包同时导入&#xff0c;那么它只会被导入一次&#xff08;例如很多包可能都会用到 fmt 包&#xff0c;但 它只会被导入一次&#x…

Paint 学习笔记

目录 ippaint 外扩对象 LCM_inpaint_Outpaint_Comfy&#xff1a; 不支持文字引导 ippaint https://github.com/Sanster/IOPaint 外扩对象 https://www.iopaint.com/models/diffusion/powerpaint_v2 GitHub - open-mmlab/PowerPaint: [ECCV 2024] PowerPaint, a versatile …

【C++】深入理解 C++ 中的继承进阶:多继承、菱形继承及其解决方案

个人主页: 起名字真南的CSDN博客 个人专栏: 【数据结构初阶】 &#x1f4d8; 基础数据结构【C语言】 &#x1f4bb; C语言编程技巧【C】 &#x1f680; 进阶C【OJ题解】 &#x1f4dd; 题解精讲 目录 C继承机制详解与代码示例&#x1f4cc;1. 继承的基本概念&#x1f4cc; 2.…

【MATLAB源码-第218期】基于matlab的北方苍鹰优化算法(NGO)无人机三维路径规划,输出做短路径图和适应度曲线.

操作环境&#xff1a; MATLAB 2022a 1、算法描述 北方苍鹰优化算法&#xff08;Northern Goshawk Optimization&#xff0c;简称NGO&#xff09;是一种新兴的智能优化算法&#xff0c;灵感来源于北方苍鹰的捕猎行为。北方苍鹰是一种敏捷且高效的猛禽&#xff0c;广泛分布于北…

C#中的二维数组的应用:探索物理含义与数据结构的奇妙融合

在C#编程中&#xff0c;二维数组&#xff08;或矩阵&#xff09;是一种重要的数据结构&#xff0c;它不仅能够高效地存储和组织数据&#xff0c;还能通过其行、列和交叉点&#xff08;备注&#xff1a;此处相交处通常称为“元素”或“单元格”&#xff0c;代表二维数组中的一个…

利用uniapp开发鸿蒙:运行到鸿蒙模拟器—踩坑合集

从uniapp运行到鸿蒙模拟器上这一步&#xff0c;就有非常多的坑&#xff0c;一些常见的坑&#xff0c;官网都有介绍&#xff0c;就不再拿出来了&#xff0c;这里记录一下官网未记录的大坑 1.运行路径从hbuilderx启动鸿蒙模拟器 解决方法&#xff1a; Windows系统&#xff0c;官…

跨平台WPF框架Avalonia教程 十三

AutoCompleteBox 自动补全输入框 自动补全输入框提供了一个供用户输入的文本框和一个包含可能匹配项的下拉列表。下拉列表会在用户开始输入时显示&#xff0c;并且每输入一个字符&#xff0c;匹配项都会更新。用户可以从下拉列表中选择匹配项。 文本与可能项匹配的方式是可配…

开发中使用UML的流程_02 CIM-1:定义业务流程

CIM-1定义业务流程&#xff08;业务用例模型&#xff09;的生成&#xff0c;有下列两项&#xff1a; 1.业务用例图 2.业务用例简述 业务用例图的主要组成元素是业务用例和业务执行者。 图中的一个业务用例代表一条业务流程&#xff0c;业务执行者则代表位于业务组织外但会启动…

Streamlit + AI大模型API实现视频字幕提取

简介 在本文中&#xff0c;我将带你探讨如何使用Streamlit和AI大模型API来实现视频字幕提取的技术。Streamlit是一个开源的Python库&#xff0c;用于快速构建数据应用的Web界面&#xff0c;而AI大模型API&#xff0c;如OpenAI&#xff0c;提供了强大的语言处理能力&#xff0c…

c++--------《set 和 map》

c--------《set 和 map》 1 set系列的使⽤1.1 set类的介绍1.2 set的构造和迭代器1.3 set重要接口 2 实现样例2.1: insert和迭代器遍历使⽤样例&#xff1a;2.2: find和erase使⽤样例&#xff1a; 练习3.map系列的使用3.1 map类的介绍3.1.1 pair类型介绍 3.2 map的数据修改3.3mu…