惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
U
Unit 42
Google DeepMind News
Google DeepMind News
博客园 - 司徒正美
Y
Y Combinator Blog
F
Fortinet All Blogs
云风的 BLOG
云风的 BLOG
T
Tailwind CSS Blog
G
Google Developers Blog
酷 壳 – CoolShell
酷 壳 – CoolShell
罗磊的独立博客
D
DataBreaches.Net
T
The Blog of Author Tim Ferriss
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
MyScale Blog
MyScale Blog
N
Netflix TechBlog - Medium
Microsoft Security Blog
Microsoft Security Blog
GbyAI
GbyAI
P
Proofpoint News Feed
Jina AI
Jina AI
B
Blog RSS Feed
腾讯CDC
阮一峰的网络日志
阮一峰的网络日志
D
Docker

博客园 - 夏之夜

Linux 学习笔记之(十四)二进制分析工具 Shell命令集锦(一) Postgres 数据库(三)常见DDL命令 elasticsearch 学习笔记之五 备份还原开源方案比较 elasticsearch 学习笔记之四 快照 GO 学习笔记之一 环境安装 GO 学习笔记之零 (四)字符串处理集锦 GO 学习笔记之零 (三)常见问题处理集锦 GO 学习笔记之三 基础语法(5) 切片 GO 学习笔记之三 基础语法(12)文件操作 GO 学习笔记之五 编程(三)单元测试 ( VSCODE工具运行 ) GO 学习笔记之三 基础语法(11) 数据类型转换 GO 学习笔记之零 (二)git 操作(VSCODE) GO 学习笔记之零 (一)GO推荐的工程目录结构 Git 学习笔记之(六)windows 上 git 工具 安装 GO 学习笔记之二 常用命令集锦 elasticsearch 学习笔记之一 elasticdump elasticsearch 学习笔记之二 常见接口 专题(二十) cut
GO 学习笔记之四 工具(1)远程调试工具 dlv
夏之夜 · 2025-08-27 · via 博客园 - 夏之夜

一、背景

    go 开发的程序需要编译成二进制放在环境上之后,通过 ./二进制文件名称 (linux服务器上的启动方式) 进行启动。 当程序允许过程中,如果发现有问题,此时希望能够 向Java 一样可以通过工具进行代码远程调试,这样可以更快发现问题。此时可以使用 dlv 工具。

二、安装

1、手动安装

     当需要调试的服务器是离线的情况下,此时我们希望能够进行手动安装

1.1  下载源码 (Releases · go-delve/delve

由于我的go版本使用的是 1.24.2, 所以这里也下载了 1.24.2 对应的源码

1.2 编译源码

  • 将下载的 delve-1.24.2.tar.gz  上传到服务器上(本文章放在了 /opt/go/tool  下,go 安装在了 /opt/go/go 下)
  • tar -zxvf delve-1.24.2.tar.gz 
  • cd delve-1.24.2
  • go build github.com/go-delve/delve/cmd/dlv   在当前目录下生成了 dlv文件

1.3 安装

  • 将 dlv 文件移动动 go path 目录下。  (\cp dlv /opt/go/go/bin)
  • dlv version   查看版本

2、利用 go 环境进行安装

  环境中已经安装上了go,且该环境可以连网络 或者 go env 中的代理可以连接上,此时可以利用go 直接安装 dlv

2.1 

三、配置远程调试环境

1、在开发工具 Visual Studio Code 中配置 dlv

  • 在开发工具中打开你的 go 工程
  • 打开调试模式菜单下的配置 。。。  左侧点击“有爬虫的图标”,点击上侧的 的下拉图标,可以看到 一些菜单, 点击 “添加配置(xxxx)”,其中 xxxx 是你的go程序目录名称

  • 右侧出现 launch.json文件

2、配置 launch.json

   在文件中添加如下配置内容

  • name:调试名称
  • type :默认 go
  • request:attach
  • mode:remote
  • remotePath:填写远程服务器上 go 二进制程序 源码所在路径
  • port:远程服务器上开启的 dlv 调试端口
  • host:远程服务器的IP
  • trace:verbose
  • showLog:true     是否打开日志

3、将go 二进制程序的源码放到 远程服务器上

四、启动远程调试

1、远程服务器 开启 dlv 调试进程

  • 远程到服务器 go 二进制源码所在目录下
  • dlv debug --headless --listen=:2366 --api-version=2 --log

可以看到 启动在 2366端口上,且go二进制程序已经运行

2、启动 Visual Studio 上的 远程调试

 

3、在 Visual Studio 上的 dlv调试时开启dlv日志(待确认)

3.1 Visual Studio 上 开启日志

1) 选择设置图标,打开设置菜单

2345

2)出现 设置页面,输入 log level , 将 remote.ssh 更改成 trace 级别

3)Ctrl+ Shift + U 打开输出面板,选择 Go Debug 模式

image

3.2 launch.json 上配置日志相关配置项

  需要加上两个配置项:

"trace": "verbose",
"showLog": true,

 12345

 4、当程序启动有自己的用户账号时,dlv 联调启动也需要通过该用户账号启动

4.1 前提条件

  • 系统已经安装了go环境(可以使用root安装,但是此时需要将go设置在系统环境变量path中)
  • 系统已经安装了dlv环境(可以使用root安装,但是此时需要将go设置在系统环境变量path中)
  • 程序安装目录所属用户为其自己的用户(非root)和用户组,且所有目录和文件权限为755,表示只有自己的用户才可以对安装目录下进行读写,其它用户只能读;
  • 已将源代码上传到程序安装目录可执行程序所属目录下,并进行了赋权,即属于自己的用户和用户组,权限为755;

4.2 操作

  • cd 源代码根目录下
  • 执行:sudo -u app-service env PATH=$PATH:/usr/local/go/bin dlv debug --listen=:2366 --headless=true --api-version=2 --log     // app-service:自己的用户名;/usr/local/go/bin:本案例是将go二进制程序文件以及dlv的文件全部放在了/usr/local/go/bin 下
  • 或执行:sudo -u app-service env PATH=$PATH:/usr/local/go/bin bash -c "dlv debug --listen=:2366 --headless=true --api-version=2 --log"
  • 成功执行dlv debug 命令之后,需要 在 Visual studio code 工具中启动远程调试

4.3 遇到的问题

1)执行dlv命令时,控制台会输出 权限不足

5、当要远程调试的程序非服务而是go开发的某个工具

5.1 前提条件

  • 系统已经安装了go环境(可以使用root安装,但是此时需要将go设置在系统环境变量path中)
  • 系统已经安装了dlv环境(可以使用root安装,但是此时需要将go设置在系统环境变量path中)
  • 已将源代码上传到程序安装目录可执行程序所属目录下,并进行了赋权,即属于自己的用户和用户组,权限为755;
  • 工具启动的时候需要传参数(这个是非必要的,有的工具可以不传参数)

5.2 操作

5.2.1 源码上传到远程服务器手动启动dlv进行远程调试

1) VSCODE 工具中 launch.json 的配置
{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
           {
            "name": "Connect to server",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "port": 2367,
            "host": "10.19.214.77",
            "trace": "verbose",
            "showLog": true,
             "logOutput": "debugger",
           "debugAdapter": "dlv-dap",
           "dlvFlags": [
                "--check-go-version=false"
            ],
            "substitutePath": [
                {
                    "from": "${workspaceFolder}",
                    "to": "/xxxx/backupRestore"    //该字段值为远程服务器上工具源代码所在目录
                }
            ] 
        }
    ]
}
2)工具主入口函数 main.go 入口处打上断点
3)远程服务器
  • cd /xxxx/backupRestore 目录下
  • 将源代码上传到该目录下
  • 执行 dlv debug  --headless --listen=:2367 --api-version=2   --log  --参数1 参数2 参数3  命令开启dlv
4) VSCODE上启动远程调试

5.2.2 直接将go源码编译后的二进制文件上传到远程服务器手动启动dlv进行远程调试

1)重新编译go源码生成工具二进制文件 并上传到 远程服务器 /xxxx/backupRestore 目录下

   也可以直接将源代码上传到远程服务器上,通过以下命令生成 prog 二进制工具文件

# 不要加 -s -w
go build -o prog main.go
# 或者显式加上 debug 标志(Go 1.24+ 默认行为,旧版本可能需要)
go build -gcflags="all=-N -l" -o prog main.go 
# 注意:-N -l 会关闭优化和内联,这对调试是必须的,但会影响性能。
# 如果是生产二进制调试,至少保证没有 strip 符号表。
 2)手动通过dlv启动二进制工具进程
 3) VSCODE 启动调试
  •  VSCODE 中的 lanuch.json 配置仍同上
  • 在main.go 文件上打上断点
  • 启动调试模式

5.2.3 工具的参数通过VSCODE的配置传入非dlv传入启动远程调试

五、用法深入研究

六、常见问题

1、启动go文件不存在于程序源码根路径下且程序依赖C++库。

1.1  具体场景描述

main.go文件不存在,程序入口go文件不在源代码根目录下,而是在其它子目录下;代码中存在加载C++库文件的逻辑。目录结构如下:

image

 1.2 问题

1.2.1  远程服务器执行 dlv debug 命令系列问题

此情况下,通过dlv调式(在源码根路径下 -- go.mod 所在目录, 执行dlv 命令: dlv debug --listen=:2366 --headless=true --api-version=2 --log  ./core/start/start.go),遇到如下问题:

1.2.1.1 直接执行  dlv debug --listen=:2366 --headless=true --api-version=2 --log  ./core/start/start.go  提示 找不到C++库提供的方法

image

这个表示在 dlv debug 的时候去生成对应的 可执行文件时找不到需要链接的 C++库文件。

因此通过资料查找,可使用 --build-flags 指定 需要链接库的绝对路径,但仍出现 1.2.1.2 的问题。

 1.2.1.2  直接执行  dlv debug --build-flags="-ldflags='-L/opt/xxx/x86/base/identify/lib/linux/x86_64 -llibIdentify'" --listen=:2345 --headless ./core/start/start.go,提示 命令存在问题

 image

这个错误是因为 -L 和 -l 是 链接器标志(linker flags),但您将它们放在了 --build-flags 的 -ldflags 参数中,而 -ldflags 是传递给 Go 链接器的,格式有特定要求。直接使用 -L 和 -l 在 -ldflags 中会导致解析错误。

1.2.1.3  解决方案

a)  使用 #cgo 指令(推荐)

在您的 Go 代码(如 center.go 或相关文件)中,通过 // #cgo 指令指定链接参数:

// #cgo LDFLAGS: -L/opt/xxx/x86/base/identify/lib/linux/x86_64 -lIdentify
// #include "identify.h"  // 确保头文件路径正确
import "C"

然后直接使用 dlv debug(无需 --build-flags):

dlv debug --listen=:2345 --headless ./core/start/start.go

PS:调试的时候可以 通过 #cgo命令写入库的绝对路径,但是实际代码不能写成绝对路径,主要是因为实际安装路径不会是这个绝对路径对应的安装目录

b)  通过环境变量传递链接参数

设置 CGO_LDFLAGS 环境变量(适用于临时调试):

export CGO_LDFLAGS="-L/optxxx/x86/base/identify/lib/linux/x86_64 -lIdentify"
dlv debug --listen=:2345 --headless ./core/start/start.go
c)  使用 --build-flags 的正确格式

如果必须使用 --build-flags,需将链接器参数作为字符串传递给 -ldflags

dlv debug --build-flags="-ldflags='-extldflags \"-L/opt/xxx/x86/base/identify/lib/linux/x86_64 -lIdentify\"'" --listen=:2345 --headless ./core/start/start.go

PS:经过考虑以及使用的方便性,使用了最后一种方案

1.2.2  通过 dlv debug --build-flags 方式指定了编译时C++库路径,此时dlv成功启动,但是在VSCODE工具上配置好 launch.json远程调试之后,点击启动,dlv debug端直接报错 “/opt/xxx/x86/__debug_bin2434698469: error while loading shared libraries: libIdentify.so: cannot open shared object file: No such file or directory”

image

1.2.2.1 分析

    根据错误提示是 _debug_binxxxx 这个程序运行时找不到 要用的C++库 libIdentify.so (PS:将这个so库直接放在 _debug_binxxx 所在目录 或 入口start.go 文件所在目录都不生效,不知道为啥

1.2.2.2 解决方案

   dlv debug 在远程服务器执行之前,先 通过export 方式设置C++库路径 。命令为:

export LD_LIBRARY_PATH=/opt/xxxx/x86/:$LD_LIBRARY_PATH

image

从上图可以看到 远程联调成功开启。

 1.2.3  远程服务器上放置的源码结构与本地的一致,但是VSCODE打上断点不生效

{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Connect to server",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "remotePath": "/opt/xxx/x86",
            "port": 2366,
            "host": "10.19.219.79",
            "trace": "verbose",
            "showLog": true,
            "cwd": "${workspaceFolder}"
        },
    ]
}

这里给 入口.go 文件上打上了断点,dlv 远程调试开启之后,有如下提示:

image

 2345

1.2.3.1 分析

     根据网上的资料给出的结论均是由于本地代码路径和远程服务器上的不一致导致的,但是思考下来感觉大概率是本地没有找到正确的映射目录所致,因此查询可以设置本地和远程路径的各种配置。

1.2.3.2 解决办法
{
    // 使用 IntelliSense 了解相关属性。 
    // 悬停以查看现有属性的描述。
    // 欲了解更多信息,请访问: https://go.microsoft.com/fwlink/?linkid=830387
    "version": "0.2.0",
    "configurations": [
        {
            "name": "Connect to server",
            "type": "go",
            "request": "attach",
            "mode": "remote",
            "port": 2366,
            "host": "10.19.219.79",
            "trace": "verbose",
            "showLog": true,
            "logOutput": "debugger",
           "debugAdapter": "dlv-dap",
           "dlvFlags": [
                "--check-go-version=false"
            ],
            "substitutePath": [
                {
                    "from": "${workspaceFolder}",
                    "to": "/opt/xxx/x86"
                }
            ] 
        },
    ]
}