主要内容总结:
- 场景与问题:在帮助设置
gokrazy/rsync
实现同步RPKI
数据时,发现特定调用下rsync
接收程序会无限挂起。通过构建特定版本并尝试同步仓库可重现该问题。 - 调试技巧 1:按
Ctrl+\
(SIGQUIT
)打印堆栈跟踪:这是查看Go
程序挂起位置的简单方法,Go
运行时收到SIGQUIT
会打印堆栈跟踪然后退出进程,默认启用,可通过GOTRACEBACK
环境变量自定义,还可使用https://github.com/maruel/panicparse
程序将堆栈跟踪以更美观的形式呈现,此例中问题在于rsync
接收实现错误预期服务器发送uid/gid
列表,相关提交已修复。 - 调试技巧 2:附加
delve
调试器到进程:若仅打印堆栈跟踪不足以诊断问题,可使用交互式调试器,常用的Linux
调试器是GDB
,但调试Go
程序推荐使用delve
调试器,安装delve
后,由于默认安全设置,需使用sudo sysctl -w kernel.yama.ptrace_scope=0
允许在Linux
中附加现有进程到调试器,然后使用dlv attach
附加到挂起的gokr-rsync
进程,开始时仅看到runtime
包的函数,需切换到感兴趣的goroutine
才能看到期望的堆栈跟踪。 - 调试技巧 3:保存核心转储以备后用:若没时间即时使用调试器,可保存核心转储,通过运行程序时设置环境变量
GOTRACEBACK=crash
,可使Go
运行时使程序崩溃并让Linux
内核生成核心转储,现代Linux
系统通常使用systemd-coredump
收集核心转储,可使用coredumpctl
管理,若系统未使用systemd-coredump
,可使用ulimit -c unlimited
和设置kernel.core_pattern
sysctl设置,然后可使用coredumpctl debug --debugger=dlv --debugger-arguments=core
启动delve
调试核心转储,此例中通过核心转储可看到与之前相同的堆栈跟踪信息。 - 结论:长期来看,设置方便调试程序的环境是值得的,
Go
自带堆栈打印功能,通过GOTRACEBACK=crash
可获取核心转储,结合delve
调试器可有效诊断Go
程序问题,作者运营博客多年,欢迎支持其工作(如购买咖啡)。
**粗体** _斜体_ [链接](http://example.com) `代码` - 列表 > 引用
。你还可以使用@
来通知其他用户。