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

news2024/11/22 4:08:03

同步发布在我的博客,欢迎来点赞。
使用 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 main

import (
	"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 Int

goroutine 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.coloradmin.cn/o/2245084.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Ubuntu问题 -- 设置ubuntu的IP为静态IP (图形化界面设置) 小白友好

目的 为了将ubuntu服务器IP固定, 方便ssh连接人在服务器前使用图形化界面设置 设置 找到自己的网卡名称, 我的是 eno1, 并进入设置界面 查看当前的IP, 网关, 掩码和DNS (注意对应eno1) nmcli dev show掩码可以通过以下命令查看完整的 (注意对应eno1) , 我这里是255.255.255.…

实现一个string的indexof方法,给出时空复杂度估计

文心快码(BaiduComate)是基于百度文心大模型&#xff0c;在研发全流程全场景下为开发者提供辅助建议的智能代码助手。结合百度积累多年的编程现场大数据、外部优秀开源数据&#xff0c;可为开发者生成更符合实际研发场景的优秀代码&#xff0c;提升编码效率&#xff0c;释放“十…

ESP8266 STA模式TCP客户端 电脑手机网络调试助手

1.STA模式TCP客户端和电脑网络调试助手 2.STA模式TCP客户端和手机网络调试助手

【lamafactory BLEU ROUGLE L评测】

1、BLEU/ROUGLE评测界面 2、这个是用BLEU 和ROUGL来评测 目录&#xff1a;saves/Qwen2-7B-Chat/lora/eval_2024-11-14-16-28-19/ 在saves文件夹 生成的文件如下 all_results.json文件 说明模型在这个测试集上是不好的 3、可以查看预测结果的文件 predict_result.json

Ros Noetic 20.04 跑通mpc_ros包保姆级教程

前言: 本文将简述mpc_ros包在noetic20.04中的安装,mpc是 一种跟踪、MPC_ROS 是一个基于ROS(Robot Operating System)的模型预测控制(Model Predictive Control,MPC)库。该项目旨在为机器人控制提供一个灵活且高效的MPC实现,使得开发者能够在ROS环境中轻松集成和使用MPC…

游戏+AI的发展历程,AI技术在游戏行业的应用有哪些?

人工智能&#xff08;AI&#xff09;与游戏的结合&#xff0c;不仅是技术进步的体现&#xff0c;更是人类智慧的延伸。从最初的简单规则到如今的复杂决策系统&#xff0c;AI在游戏领域的发展历史可谓波澜壮阔。 早在2001年&#xff0c;就有研究指出游戏人工智能领域&#xff0…

HarmonyOs DevEco Studio小技巧31--卡片的生命周期与卡片的开发

Form Kit简介 Form Kit&#xff08;卡片开发服务&#xff09;提供一种界面展示形式&#xff0c;可以将应用的重要信息或操作前置到服务卡片&#xff08;以下简称“卡片”&#xff09;&#xff0c;以达到服务直达、减少跳转层级的体验效果。卡片常用于嵌入到其他应用&#xff0…

Redis的过期删除策略和内存淘汰机制以及如何保证双写的一致性

Redis的过期删除策略和内存淘汰机制以及如何保证双写的一致性 过期删除策略内存淘汰机制怎么保证redis双写的一致性?更新策略先删除缓存后更新数据库先更新数据库后删除缓存如何选择&#xff1f;如何保证先更新数据库后删除缓存的线程安全问题&#xff1f; 过期删除策略 为了…

单元测试框架gtest学习(三)—— 事件机制

前言 上节我们学习了gtest的各种宏断言 单元测试框架gtest学习&#xff08;二&#xff09;—— 认识断言-CSDN博客 本节我们介绍gtets的事件机制 虽然 Google Test 的核心是用来编写单元测试和断言的&#xff0c;但它也允许在测试执行过程中进行事件的钩取和自定义&#xf…

Unity Inspector窗口可编辑的脚本变量

Inspector可编辑的脚本变量 默认会显示的变量 在Unity中&#xff0c;为了方便我们进行一些属性的设置及调试&#xff0c;我们所写的公有基础数据类型会显示在Inspector之中&#xff0c;我们可以对他进行设置来更改它的取值。 显示私有变量 在有些情况下&#xff0c;设计代码…

力扣 LeetCode 110. 平衡二叉树(Day8:二叉树)

解题思路&#xff1a; 等于 -1 时&#xff0c;直接 return -1 class Solution {public boolean isBalanced(TreeNode root) {return getHeight(root) ! -1;}public int getHeight(TreeNode root) {if (root null) return 0;int leftDepth getHeight(root.left);if (leftDep…

unity3d————基础篇小项目(设置界面)

代码示例&#xff1a; 设置界面 using System.Collections; using System.Collections.Generic; using UnityEngine;public class SettingPanel : BasePanel<SettingPanel> {public UIButton btnClose;public UISlider sliderMusic;public UISlider sliderSound;public…

商用密码产品认证名录说明

《商用密码产品认证目录》是为贯彻落实《中华人民共和国密码法》&#xff0c;进一步健全完善商用密码产品认证体系&#xff0c;更好满足商用密码产业发展需要&#xff0c;根据《国家密码管理局 市场监管总局关于调整商用密码产品管理方式的公告》《市场监管总局 国家密码管理局…

从零做一个遥控玩具,需要学什么

遥控玩具编程是一个充满乐趣和挑战的领域&#xff0c;它完美地结合了硬件控制和软件编程。记得小时候拿着遥控器操控玩具汽车&#xff0c;总觉得神奇。如今站在程序员的视角&#xff0c;终于明白这背后是怎样的技术在支撑。 这些有趣的遥控玩具&#xff0c;其核心都是基于单片…

java的web项目如何连接数据库

mysql-connector.jar 是一个Java库文件&#xff0c;它提供了Java应用程序与MySQL数据库进行交互的接口 首先准备好这个文件&#xff0c;没有的话在网上搜索 将它放在这个位置&#xff0c;MySQL连接配置就好了&#xff0c; 如果拖不进去&#xff0c;右击项目名称&#xff0c;…

视频修复技术和实时在线处理

什么是视频修复&#xff1f; 视频修复技术的目标是填补视频中的缺失部分&#xff0c;使视频内容连贯合理。这项技术在对象移除、视频修复和视频补全等领域有着广泛的应用。传统方法通常需要处理整个视频&#xff0c;导致处理速度慢&#xff0c;难以满足实时处理的需求。 技术发…

OpenTelemetry 赋能DevOps流程的可观测性革命

原作者&#xff1a;天颇 原出处&#xff1a;微信公众号 乘云数字DATABUFF 原文地址&#xff1a;https://mp.weixin.qq.com/s/D_f31EBtLu7Rr0gahuF-bw 引言 在当今快节奏的软件开发和运维环境中&#xff0c;DevOps 已经成为主流&#xff0c;它通过整合开发和运维流程&#xff0…

计算机视觉算法——基于深度学习的高精地图算法(MapTRv2 / PivotNet / BeMapNet)

计算机视觉算法——基于深度学习的高精地图算法&#xff08;MapTRv2 / PivotNet / BeMapNet&#xff09; 计算机视觉算法——基于深度学习的高精地图算法&#xff08;MapTRv2 / PivotNet / BeMapNet&#xff09;1. MapTRv21.1 网络结构及特点1.2 Decoupled Self-Attention1.3 O…

nodejs21: 快速构建自定义设计样式Tailwind CSS

Tailwind CSS 是一个功能强大的低级 CSS 框架&#xff0c;只需书写 HTML 代码&#xff0c;无需书写 CSS&#xff0c;即可快速构建美观的网站。 1. 安装 Tailwind CSS React 项目中安装 Tailwind CSS&#xff1a; 1.1 安装 Tailwind CSS 和相关依赖 安装 Tailwind CSS: npm…

《Python网络安全项目实战》项目6 编写密码工具程序

《Python网络安全项目实战》项目6 编写密码工具程序 项目6 编写密码工具程序任务6.1 猜数字游戏任务描述任务分析任务实施6.1.1 编写基本的猜数字程序 6.1.2 为猜数字程序加入连续猜数的功能6.1.3 测试并修改程序6.1.4 给程序增加注释 任务拓展 任务6.2 编写密码工具程序任务描…