Goland 对容器中的 Go 程序断点远程调试

news2024/11/30 20:51:36

1,针对 golang 程序打断点有哪几种情况

  • 临时进程:针对临时运行一次的 Golang 脚本,比如定时统计脚本,定时推送脚本。
  • 常驻进程:针对一直在后台运行的 Golang 程序,比如 HTTP 或者 GRPC 服务。

我们现在假设不管是上面的临时进程还是常驻进程都是运行的容器中。(因为不在容器中的大家可以直接在 Goland 中进行断点 debug)

2,临时进程断点 debug?

1,首先我们需要在一个 含有 Golang 程序的容器中安装 delve(简称dlv)(debug 工具,类似 PHP 的 xdebug)

第一种安装方式:go install github.com/go-delve/delve/cmd/dlv@latest

第二种安装方式(推荐):针对我们使用的 golang 镜像,进行二次定制,直接将 delve 打包进行,dockerfile 如下

FROM golang:1.20.2 AS builder

WORKDIR /build

# 这里他的 main.go 没有直接在项目主目录,不同于其他 golang 开源项目。
RUN git clone --depth 1 --branch v1.20.2 https://github.com/go-delve/delve.git && \
    cd /build/delve/cmd/dlv && \
    go build -o /build/delve/bin/dlv


FROM golang:1.20.2

COPY --from=builder /build/delve/bin/dlv /usr/local/bin/dlv
  • 执行命令进行编译(双版本):docker buildx build --platform linux/amd64,linux/arm64 -t golang:1.20.2-debug .

备注:使用 FROM golang:1.20.2 AS builder 的语法是 Dockerfile 中的多阶段构建(Multi-stage build)功能,旨在帮助优化镜像的大小和构建过程

2,在下载好dlv的容器中的程序主目录,运行dlv的命令

dlv debug --headless --listen=:40000 --api-version=2 --accept-multiclient

如下图代表启动成功,并且监听 40000 端口,等待远程的 debug 工具(Goland/vscode等)连接。

image.png

3,配置 goland 连接第二步运行的dlv

image.png

image.png

image.png

image.png

4,使用 goland 打断点并触发 debug

image.png

3,常驻进程断点 debug?

如果你只调试一个常驻进程也可以像临时进程进行一样 debug,不过当你有多个微服务用 docker-compose 部署起来以后,一般都是启动 docker 就启动对应的 golang 程序。这个时候要去杀死这个进程再用dlv进行启动,会发现比较麻烦

这里提供一个方便的方法。就是原来的微服务配置全部不动。然后

  • 通过一个 shell 脚本,获取到容器里面运行微服务的pid。
  • 通过 dlv的 attach 操作直接入侵正在运行的goalng程序 同时暴露 40000 端口。
  • 通过 goland 的 go remote 连接暴露的 40000 端口。

细化操作如下: 1, 在容器内,编译并运行(或者直接修改 docker-compose 中的 command)一个 golang web 服务 编译并且运行:

go build -gcflags="-N -l" -o demo
./demo

这里先 build 是因为需要添加 -gcflags="-N -l" 这个参数,因为当使用go run命令运行Go代码时,无法直接添加编译器标志(例如-gcflags="-N -l"),而只有加了这个参数才可以避免 golang 在做编译时把一些代码进行忽略,导致goland无法再某一行代码上打断点且会报错:could not find statement at /usr/local/go/src/cmd/ go/main.go:24, please use a line with a statement

2,通过一个shell 脚本(dlv_debug.sh)启动 dlv

#!/bin/bash

# 配置这个程序的名字
#program_name="/data/golang_breakpoint_debug/tmp/main"
program_name="/demo"

# 获取所有程序
program_list=$(ps -ef | grep -v "air" | grep -v "/bin/sh")

# 获取包含 program_name 的程序的PID
go_app_pid=$(echo "$program_list" | awk -v pname="$program_name" '$0 ~ pname {print $2}')

echo "====== get golang program,name:$program_name pid: $go_app_pid ======"

# 运行dlv命令
dlv attach "$go_app_pid" --headless --listen=:40000 --api-version=2 --accept-multiclient

可以在容器内运行上面的 shell 脚本:

image.png

也可以在容器外面执行这个命令:

docker exec -t golang_breakpoint_debug /bin/sh -c "chmod +x /data/golang_breakpoint_debug/dlv_debug.sh && /data/golang_breakpoint_debug/dlv_debug.sh"

3,按照临时程序的debug流程一样配置goland,启动 debug

image.png

以上就是怎么在不停止golang 的常驻进程(比如 HTTP或者 GRPC 的服务)的情况下,对这个 golang 的常驻进程进行 debug。

4,全自动一键 debug(不想折腾可以跳到第五小节)

上面每次停止 debug 或者 代码更新以后都需要再去手动启动一下dlv,但是程序员是最讨厌手动的。所以得想办法解决这两个手动操作。

4.1 解决代码更新自动重启

安装一个工具包:go install http://github.com/cosmtrek/air@latest 将 app 启动命令替换为 air 启动的命令:air --build.cmd 'go build -gcflags="all=-N -l" -o demo' --build.bin="./demo"

备注:这里 air 会监听 golang 代码,当代码发生变动的时候,会自动重启。

4.2 解决每次都要手动启动dlv

配置一下before launch 来每次自动启动dlv 在go remote 里面增加一个 before launch 命令如下图

image.png

dlv_debug_out_start.sh 的 shell 脚本内容如下:

#!/bin/bash

docker exec -t golang_breakpoint_debug /bin/sh -c "chmod +x /data/golang_breakpoint_debug/dlv_debug.sh && /data/golang_breakpoint_debug/dlv_debug.sh" &

sleep 0.5

注意的第一点: 报错:the input device is not a TTY 因为一般docker 命令里面是用的 exec -it ,而如果您在命令中使用了 -t 或 --tty 选项,它会要求终端交互性,并且如果当前的输入设备不是一个 TTY,则会出现该错误。

注意的第二点: shell 脚本中需要 sleep 0.5 ,是因为这个是顺序执行,因为 shell 里面最后加了 & 所以不会阻塞,有可能 shell 运行完了,Goland 启动 debug, 但是shell 那里异步启动还没完成,会导致启动失败。

注意的第三点: 我们配置 go remote 的时候需要配置停止 debug 以后自动停止远程的dlv。

image.png

4.3 整个流程的一个回顾

完成上面的配置,基本就可以做到一键 debug 运行在 docker 中的常驻微服务。最后我们再整体回顾一下,看下这个流程是怎么走通的,假设现在有一个常驻 web 服务大体的流程是

1,docker-compose 启动所有容器,此时容器中有一个 web 服务。

2,这个时候你在 Goalnd里面打好断点,同时点击Goland 中的debug按钮。

3,点击 debug 按钮后,触发 before launch,在宿主机运行 shell 脚本(dlv_debug_out_start.sh)启动 web 服务容器内 shell 脚本(dlv_debug.sh)。

4,web 容器里面的 shell 脚本(dlv_debug.sh)获取正在运行的web服务pid,然后启动dlv劫持这个pid,同时暴露 40000 端口。

5,此时 before launch 运行完毕,Goalnd的debug客户端连接上 web 容器的40000端口,此时可以进行 debug 操作。

6,debug 完毕以后,我们关闭 debug,这个时候自动触发关闭远程dlv

7,我们修改我们需要修改的 Golang 文件,此时触发 air,重启了 web 服务

8,我们再次尝试 debug(循环 3-8)

按照以上的流程,其实我们可以给其他任何语言(PHP/jave)运行在 docker 里面的服务做添加类似的debug配置。

5,Goland 断点 debug 的基础操作教程

最后提供一个 Goland 断点 debug 页面中简单调试会用到的基础按钮的作用,具体可看下图。红色框起来的的几的按钮以及后面对这几个按钮的解释。

image.png

  • Show Execution Point (Alt + F10):如果你的光标在其它行或其它页面,点击这个按钮可跳转到当前代码执行的行。
  • Step Over (F8):步过,一行一行地往下走,如果这一行上有方法不会进入方法。
  • Step Into (F7):步入,如果当前行有方法,可以进入方法内部,一般用于进入自定义方法内,不会进入官方类库的方法。
  • Force Step Into (Alt + Shift + F7):强制步入,能进入任何方法,查看底层源码的时候可以用这个进入官方类库的方法。
  • Step Out (Shift + F8):步出,从步入的方法内退出到方法调用处,此时方法已执行完毕,只是还没有完成赋值。
  • Run to Cursor (Alt + F9):运行到光标处,你可以将光标定位到你需要查看的那一行,然后使用这个功能,代码会运行至光标行,而不需要打断点。
  • Evaluate Expression (Alt + F8):计算表达式。

另外贴一个 PHP 的 断点 debug 教程,我记得好像很多是 PHP 转 Golang:

以上,基本就是全部的利用 Goland 对 运行在 docker 里面的 goland 程序进行 debug 的配置和基本操作了,创作不易,欢迎点赞收藏,以及如果有疑问或者改进意见,欢迎在评论区留言。

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

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

相关文章

【多线程面试题二十一】、 分段锁是怎么实现的?

文章底部有个人公众号:热爱技术的小郑。主要分享开发知识、学习资料、毕业设计指导等。有兴趣的可以关注一下。为何分享? 踩过的坑没必要让别人在再踩,自己复盘也能加深记忆。利己利人、所谓双赢。 面试官: 分段锁是怎么实现的&am…

最新ChatGPT商业运营系统源码+支持GPT4/支持ai绘画+支持Midjourney绘画

一、AI创作系统 SparkAi创作系统是基于OpenAI很火的ChatGPT进行开发的Ai智能问答系统和Midjourney绘画系统,支持OpenAI-GPT全模型国内AI全模型。本期针对源码系统整体测试下来非常完美,可以说SparkAi是目前国内一款的ChatGPT对接OpenAI软件系统。那么如…

[common c/c++] ring buffer/circular buffer 环形队列/环形缓冲区

前言: ring buffer / circular buffer 又名环形队列 / 环形缓冲区,其通过开辟固定尺寸的内存来实现反复复用同一块内存的目的。由于预先开辟了固定尺寸的内容,所以当数据满的时候,可以有两种处理方式,具体使用哪一种按…

DC系列 DC:3

DC系列 DC:3 文章目录 DC系列 DC:3调试靶机信息收集IP端口信息收集 框架漏洞利用joomscan扫描工具利用msf工具利用(无法使用)kali漏洞库利用sqlmap利用 文件上传提权 调试靶机 点击虚拟机设置选择CD/DVD点击高级将IDE调成画面中这个选项 信息收集 IP端口信息收集 对自己网…

【实战Flask API项目指南】之七 用JWT进行用户认证与授权

实战Flask API项目指南之 用JWT进行用户认证与授权 本系列文章将带你深入探索实战Flask API项目指南,通过跟随小菜的学习之旅,你将逐步掌握 Flask 在实际项目中的应用。让我们一起踏上这个精彩的学习之旅吧! 前言 当小菜踏入Flask后端开发…

java匿名类

什么是匿名实现类? 定义: 在java中,匿名实现类对象是一种特殊的对象,它是通过匿名类来创建的。匿名类是一个没有名字的类,它是在代码中直接定义和实例化的。匿名实现类对象通常用于实现接口或者扩展类,因为…

Express框架开发接口之实现七牛云上传图片功能

安装和配置multer 注意:使用express.urlencoded()中间件无法解析multipart/form-data格式的请求体 数据。 当前项目,推荐使用 multer 来解析multipart/form-data格式的表单数据。https://www.npmjs.com/package/multer npm i multer 导入并配置multer &a…

【Apifox新支持】如何管理与调试 Dubbo 项目?

一、引入Dubbo3 不会介绍 Dubbo 如何使用,咱只提一嘴,然后说如何去测试 Dubbo 服务。Dubbo3 除了保持 2.x 的经典架构之外,还以解决微服务的进程通信为主要职责,通过丰富的服务治理能力来更好的管控微服务服务集群,简…

(免费领源码)java#springboot#MYSQL 电影推荐网站30760-计算机毕业设计项目选题推荐

摘 要 随着互联网时代的到来,同时计算机网络技术高速发展,网络管理运用也变得越来越广泛。因此,建立一个B/S结构的电影推荐网站;电影推荐网站的管理工作系统化、规范化,也会提高平台形象,提高管理效率。 本…

玩转AIGC(人工智能生成内容)需要一些小技巧

玩转AIGC(人工智能生成内容)的确需要一些技巧,而Prompt提示词的选择非常关键,可以影响到生成的答案。以下是一些与AI对话的技巧和咒语示例: 1,明确问题 确保你的Prompt清晰明了,包括主题、问题…

领星ERP如何无需API开发轻松连接OA、电商、营销、CRM、用户运营、推广、客服等近千款系统

领星ERP(LINGXING)是一款专业的一站式亚马逊管理系统,帮助卖家构建完整的数据化运营闭环。,致力于为跨境电商卖家提供精细化运营和业财一体化的解决方案。 官网:https://erp.lingxing.com 集简云无代码集成平台&…

四川思维跳动:抖店运营服务商的运营方案

抖店运营服务商,作为一种新兴的商业模式,正逐渐受到广大电商从业者的重视和青睐。抖店运营方案不仅可以帮助创业者快速进入电商行业,还可以为他们提供全方位的运营支持和服务。下面四川思维跳动小编就来详细介绍一下抖店运营服务商的优势和价…

防止重复提交请求

前景提要: ts 简易封装 axios,统一 API 实现在 config 中配置开关拦截器 axios 实现请求 loading 效果 用一个数组保存当前请求的 url,此时还未响应。如果再次发起同样请求,比对 url 发现已经存在数组中,则拦截请求&a…

基于类电磁机制算法的无人机航迹规划-附代码

基于类电磁机制算法的无人机航迹规划 文章目录 基于类电磁机制算法的无人机航迹规划1.类电磁机制搜索算法2.无人机飞行环境建模3.无人机航迹规划建模4.实验结果4.1地图创建4.2 航迹规划 5.参考文献6.Matlab代码 摘要:本文主要介绍利用类电磁机制算法来优化无人机航迹…

【JAVA学习笔记】58 - 泛型

项目代码 https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter15/src/com/yinhai/generic_ https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter15/src/com/yinhai/customgeneric_ 一、泛型的入门和好处 1)请编写程序,…

c#的反编译工具ISPY和net reflector 使用比较

我有一份Asp.net程序需要修改,但没有源码,只有dll,需要使用反编译工具回复源码,尝试使用了市面上的两种主流的工具ISPY和net reflector ,最终用ISPY恢复了源码。 比较 ISPY 恢复的代码和实际有差距,但还能…

2023年高校大数据实训平台需求

2023 年大数据实训平台的需求量呈现出快速增长的趋势。随着大数据技术的不断普及和应用,越来越多的企业和高校意识到大数据人才培养的重要性。因此,对大数据实训平台的需求量不断增加。 据了解分析,大数据实训平台需求量增加包括以下方面的原…

系统架构设计师(第二版)学习笔记----层次式架构设计理论与实践

【原文链接】系统架构设计师(第二版)学习笔记----层次式架构设计理论与实践 文章目录 一、层次式体系结构概述1.1 软件体系结构的作用1.2 常用的层次式架构图1.3 层次式体系可能存在的问题点 二、表现层框架设计2.1 MVC模式2.1.1 MVC三层模式2.1.2 MVC设…

【错误解决方案】ModuleNotFoundError: No module named ‘pycocotools‘

1. 错误提示 在python程序中,通过导入一个名为pycocotools的模块,但Python提示找不到这个模块。 错误提示:ModuleNotFoundError: No module named pycocotools 2. 解决方案 pycocotools是一个Python包,它提供了用于处理COCO数据…

一文看懂MySQL 5.7和MySQL 8到底有哪些差异?

目录 ​编辑 引言 1、数据字典和系统表的变化 2、JSON支持的改进 3、新的数据类型 4、安全性增强 5、性能改进 6、InnoDB存储引擎的改进 结论 引言 MySQL作为最常用的开源关系型数据库管理系统之一,一直在不断发展和改进。随着时间的推移,MySQ…