HOWTO · Bash
如何在 Bash 脚本中运行 GDB
使用调试符号编译 C 程序、从 Bash 在 GDB 下运行它、传递程序参数,并自动执行调试器命令。
本页内容
要从 Bash 在 GDB 下运行程序,请使用 --args 调用 gdb,其后跟上可执行文件及其参数。当脚本应自动启动程序时,添加 -ex run;若不添加,GDB 会打开其提示符并等待命令。本指南准备一个小型 C 程序、安全地构建命令,并展示交互式、断点和命令文件三种工作流程。为本文提供的运行时环境不包含 GDB,因此下面的调试器命令仅作记录,并不作为已执行的输出呈现。
为 GDB 准备程序
下面的示例将一个小型 C 程序写入临时目录,使用 GCC 的 -g 选项对其进行编译,然后带一个参数运行它。调试符号使 GDB 能够将机器指令与源代码行和变量关联起来。脚本退出时,临时文件会被删除。
set -eu
workdir=$(mktemp -d)
trap 'rm -rf "$workdir"' EXIT
cat > "$workdir/example.c" <<'C'
#include <stdio.h>
int main(int argc, char **argv) {
if (argc > 1) {
printf("Argument: %s\n", argv[1]);
}
return 0;
}
C
gcc -g -o "$workdir/example" "$workdir/example.c"
cd "$workdir"
program=./example
"$program" hello
printf 'gdb --quiet -ex run --args %s hello\n' "$program"
Argument: hello
gdb --quiet -ex run --args ./example hello
该可执行文件接受一个可选值;此处会打印 hello。启动 GDB 时,在 --args 之后使用相同的可执行文件路径和参数。下面的 GDB 命令要求运行它们的机器上安装有 GDB 和已编译的可执行文件。
从 Bash 脚本运行 GDB
Bash 脚本可以将可执行文件和参数存储在变量中,然后在 --args 之后传递它们。前面的示例预览了组装好的命令,无需安装 GDB。要从脚本启动真正的调试会话,请使用 gdb --quiet -ex run --args "$program" "$argument"。--quiet 选项会抑制 GDB 的介绍信息,而 -ex 会运行其后的 GDB 命令。-ex run 会启动程序;省略它则会让 GDB 停在 (gdb) 提示符处。要进行交互,请省略 -ex run 并在该提示符处输入 run。请为变量展开加上引号,使包含空格的参数仍保持为单个参数。这些调试器调用要求运行脚本的机器上安装有 GDB 和已编译的 example 可执行文件。
设置断点并检查执行过程
要在程序进入 main 时暂停,请在 -ex run 之前添加 -ex 'break main',例如:gdb --quiet -ex 'break main' -ex run --args ./example hello。GDB 会在执行 main 的函数体之前停在断点处。在提示符处,使用 print argc 和 print argv[1] 检查参数,然后使用 continue 继续。bt 命令会打印当前调用栈;它在执行暂停时(例如在断点处或崩溃之后)非常有用。已经退出的正常运行没有可供检查的活动调用栈。
使用命令文件自动化 GDB
对于可重复的调试步骤,请将 GDB 命令放入名为 gdb_commands.txt 的纯文本文件中:
break main
run
print argc
使用 gdb --quiet -x gdb_commands.txt --args ./example hello 加载该文件。GDB 会按顺序处理所列命令:在 main 处停止、运行程序,然后打印 argc。对于嵌入 Bash 脚本的短命令序列,请使用 -ex;对于保存在单独文件中的更长或可复用的序列,请使用 -x。命令文件包含 GDB 命令,而 --args 提供可执行文件和程序的参数。