扫描器 debug 调优记录
啥时候我能写一个安全行业人手一个工具
go 有个恶心的地方,就是不能捕获子进程的 panic, 每个子进程都使用 recover()去捕获,太麻烦,不现实,而且你也没办法确保你引入的第三方包会捕获子进程; 这就导致我在写扫描器时,某个进程发生 panic , 屏幕输出很长很长的堆栈信息,一屏幕都滚动不完,而且我使用 screen 放到后台,导致我就只能看到非常小的一部分。
所以只能找其他路子了,下面记录一下使用 dlv 来排查,寻找导致 panic 的地方
panic 错误
使用 dlv 调试,前提二进制文件再生成时,不能指定-ldflags "-s -w"
启动前,先执行
1 | ulimit -c unlimited |
ulimit命令用于控制shell程序的资源
-c <core文件上限> 设定core文件的最大值,单位为区块
unlimited标识不做限制
GOTRACEBACK 来控制Golang panic stack trace输出的信息
1 | GOTRACEBACK的设置值有几种,下面分别说明: |
加上这两句,当程序异常终止时,就是打印堆栈信息,然后会在当前目录下生成一个`core文件
- 安装dlv
- 调试 coredump 文件
dlv core {这里是你的程序} {这里是coredump文件} --check-go-version=false
然后使用 goroutines -with running, 查看运行的协程
看到编号 23794 有个 * 标记
切换到对应的协程goroutine 23794 ,再试用 bt 子命令分析堆栈的错误
emmm,我看代码没看出来为啥会发生panic
然后求助ChatGPT
按照给出的修复方式,然后运行一段时间又出现 panic ,还是这里,emmmmmmm
我大概知道了,我将 AfrogFingerPrintMap 变量定义到了外部,是一个全局变量, 当多协程使用时,就会发生他说的情况。修复方案就是将变量定义为局部变量,互不干扰。
教训就是除了一些常量外,尽量不要将变量定义为全局的,不然多协程下修改值必出问题
还有就是这里重复初始化,可能会导致内存分配出现问题而导致程序崩溃
oom-killer
运行一段时间,整个程序被 killed ,小机器不行啊, 又没钱升级,只能找找程序的原因,看看哪里占用了过多的内存,调优性能
一开始使用保存文件的方式
1 | f, _ := os.Create("mem.prof") |
go tool pprof -http=0.0.0.0:80 SScan-agent mem.prof
但是看到的信息好像不是很全,之后使用
1 | go func() { |
通过 http://xxx.xxx.xx.xx/debug/pprof/ 查看,不好的地方就是要在程序被 killed 前看数据,不过也还好,这个可以监控内存使用率,超过一定阈值通知,然后去看debug/pprof/ 相关信息就好了,最终也找到了原因。
比如 goroutine 居高不下,可能就是哪里发生了死锁,比如 ratelimit 用完不释放
还有就是 heap 也是居高不下,比如我用到了 httpx wappalyzergo、fastdialer 重复初始化,内存没有释放掉,导致了被 killed
看代码是因为 fastdialer 用完没有调用 close()
参考
https://zhuanlan.zhihu.com/p/413527587
https://github.com/go-delve/delve/blob/master/Documentation/cli/README.md#goroutines











