使用 GDB 调试 dockercompose 服务

问题描述 投票:0回答:1

我正在尝试通过 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

gdb 主机日志

c linux docker-compose gdb gdbserver
1个回答
1
投票

要使用

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
,而不仅仅是可能因重新编译或不同的构建参数而不同的本地副本。
如果您的应用程序使用共享库,则还需要使用调试符号来编译它们。如果共享库缺少调试符号,GDB 将无法提供有关其中执行的代码的信息。

验证主机上的源文件与用于在 Docker 容器内构建二进制文件的源文件完全匹配。任何不匹配都可能导致调试器显示不正确的信息。
GDB 需要源文件的正确路径。如果二进制文件是在不同的环境中编译的(例如,在 Docker 容器内),则二进制文件中嵌入的源路径可能与运行 GDB 的主机系统上的路径不匹配。在GDB中使用

dir
命令添加源文件的搜索目录:
(gdb) dir /path/to/source/files
.

© www.soinside.com 2019 - 2024. All rights reserved.