我正在尝试通过 GDB 调试通过 docker-compose 运行的服务。 我有下面的 docker-compose 有两个服务,我没有使用 gdb 调试“service_test”服务。我正在公开端口 5000。
我使用以下命令启动 docker-compose。 “start.sh”文件具有“docker-compose up”命令。
gdbserver localhost:5000 start.sh
在另一个终端中,我使用以下命令进行连接,该命令启动 gdb 提示符终端,
gdb service_exec
在 GDB 提示终端中,我尝试使用以下命令连接到目标主机。
target remote localhost:5000
continue
虽然它执行目标程序,但无法跟踪主机的错误。 GDB 提示符卡在下面的附加消息中,并且在 gdbserver 中程序运行时出现错误。
知道这可能是什么问题以及如何解决这个问题吗?
我尝试了安德鲁评论的以下设置命令,但它似乎不起作用。添加以下两个设置命令后,程序不会在 gdbserver 终端中执行,并且 hiost 终端在链接中显示以下日志。
set follow-fork-mode child
set detach-on-fork off
要使用
service_test
调试 gdb
服务,您应该确保该服务是通过 gdbserver
启动的。您正在尝试使用 gdbserver
启动 start.sh
,这可能会启动整个 docker-compose
设置,而不仅仅是使用 service_test
启动 gdbserver
服务。
尝试在您的
docker-compose.yml
文件中使用如下命令:
command: gdbserver localhost:5000 /usr/local/bin/service_exec --name crash --logger 1
正常运行
docker-compose up
,无需 start.sh
。这应该启动 redis
服务和 service_test
服务,其中 gdbserver
侦听端口 5000(如“如何使用 GDBServer 示例在远程服务器上调试程序”中所述,作者:Lakshmanan Ganapathy)。
使用您指定的命令从
gdbserver
客户端连接到 gdb
:
gdb service_exec
target remote localhost:5000
continue
注意:确保您的
service_exec
二进制文件是使用调试符号编译的(如果您使用的是 -g
,则为 gcc
标志)。
Host Machine Docker Container
+------------------+ +------------------------+
| gdb service_exec | | service_test |
| target remote | (Port 5000) | gdbserver :5000 <cmd> |
| localhost:5000 |------------------------->| |
+------------------+ +------------------------+
如果调整后问题仍然存在,则可能与您的服务的分叉行为有关。 set follow-fork-mode child
中的命令
set detach-on-fork off
和 gdb
旨在在分叉后将 gdb
附加到子进程。如果服务被设计为派生子进程,并且您想要调试子进程,则这些设置是必要的。
如果我们尝试调试源目标文件怎么办?我尝试了你提到的方法,并得到类似“
”的错误。Program received signal SIGILL, Illegal instruction
但无法追溯到实际代码。运行“”命令时,它会显示“bt
”和“??
”。没有显示可追溯至代码源的信息。__dso_handle ()
您知道如何解决这个问题吗?
当您遇到
SIGILL, Illegal instruction
错误并且无法在GDB中使用bt
(backtrace)命令追溯到源代码时,通常表明调试信息丢失或不完整。 ??
和通用函数名称(如__dso_handle ()
)的存在通常意味着GDB找不到源代码或调试符号不可用。以下是排查和解决此问题的一些步骤:
确保您的源代码是使用调试符号(
-g
标志)编译的:gcc -g -o service_exec source_file.c
。-O2
或 -O3
)有时会使调试变得更加困难,因为源代码和生成的代码之间的关系不太清楚。如果可能,请使用 -O0
进行编译以在调试时禁用优化。
确保您在 Docker 容器内运行的同一二进制文件上运行
gdb
,而不仅仅是可能因重新编译或不同的构建参数而不同的本地副本。验证主机上的源文件与用于在 Docker 容器内构建二进制文件的源文件完全匹配。任何不匹配都可能导致调试器显示不正确的信息。
GDB 需要源文件的正确路径。如果二进制文件是在不同的环境中编译的(例如,在 Docker 容器内),则二进制文件中嵌入的源路径可能与运行 GDB 的主机系统上的路径不匹配。在GDB中使用
dir
命令添加源文件的搜索目录:(gdb) dir /path/to/source/files
.