gdb
Compare original and translation side by side
🇺🇸
Original
English🇨🇳
Translation
ChineseGNU Debugger (GDB) Skill
GNU调试器(GDB)技能
Non-blocking GDB debugging for AI agents. Trace live processes, set conditional
breakpoints, and inspect program state while the agent stays responsive and can
multitask.
为AI Agent提供非阻塞式GDB调试功能。可追踪实时进程、设置条件断点,并在保持Agent响应能力及多任务处理的同时检查程序状态。
How It Works
工作原理
Agents are single-threaded — if an agent runs GDB directly and waits for a breakpoint, it blocks entirely. It can't respond to the user, answer questions, or change strategy until the breakpoint fires (which may take a very long time).
This skill avoids that by running GDB in the background via a named pipe. The agent sends commands by writing to the pipe and reads results from a log file, so it never blocks. Instead of traditional breakpoints, it uses (dynamic printf) — a GDB feature that prints formatted output when hit and automatically continues execution without stopping.
dprintfThis means the agent can:
- Start a debug session and immediately return to the user.
- Sample the log file periodically to report progress.
- Multitask (e.g., search the web, edit code) while the target process runs.
- Interrupt and modify tracepoints dynamically without killing the session.
The skill includes helper scripts that encapsulate all the pipe management, signal handling, and quoting logic — so any agent that can run shell commands can use it.
Agent是单线程的——如果Agent直接运行GDB并等待断点触发,它会完全阻塞。在断点触发前(这可能需要很长时间),它无法响应用户、回答问题或调整策略。
本技能通过命名管道在后台运行GDB来避免这种情况。Agent通过向管道写入命令并从日志文件读取结果,因此永远不会被阻塞。它使用**(动态printf)替代传统断点——这是GDB的一项功能,当触发时会打印格式化输出,并自动继续执行**而不会停止程序。
dprintf这意味着Agent可以:
- 启动调试会话后立即返回用户界面。
- 定期采样日志文件以报告进度。
- 在目标进程运行时多任务处理(例如,搜索网页、编辑代码)。
- 动态中断并修改追踪点,而无需终止会话。
本技能包含封装了所有管道管理、信号处理和引用逻辑的辅助脚本——因此任何能运行shell命令的Agent都可以使用它。
Core Concepts
核心概念
- Background Execution: GDB runs in the background. You interact with it by writing to its standard input (stdin).
- Non-Blocking: Use (dynamic printf) instead of
dprintf. This inserts a printf call and continues execution immediately.break - Log Sampling: GDB output is redirected to a file (). You read this file to see the trace.
set logging file ... - Dynamic Updates: proper interrupt handling is required to add/remove tracepoints on a running process.
- 后台执行:GDB在后台运行。你通过写入其标准输入(stdin)与之交互。
- 非阻塞:使用(动态printf)替代
dprintf命令。这会插入一个printf调用并立即继续执行。break - 日志采样:GDB输出被重定向到文件()。你通过读取该文件查看追踪结果。
set logging file ... - 动态更新:需要正确的中断处理才能在运行中的进程上添加/移除追踪点。
Prerequisites & Setup
前提条件与设置
Requirements
要求
- Linux OS
- (recommended) or
gdb-multiarchgdb
- Linux操作系统
- (推荐)或
gdb-multiarchgdb
Installation
安装
bash
undefinedbash
undefinedDebian/Ubuntu
Debian/Ubuntu
sudo apt-get update && sudo apt-get install -y gdb-multiarch
sudo apt-get update && sudo apt-get install -y gdb-multiarch
Fedora/RHEL
Fedora/RHEL
sudo dnf install -y gdb
sudo dnf install -y gdb
Arch
Arch
sudo pacman -S gdb
sudo pacman -S gdb
Verify
验证
gdb-multiarch --version || gdb --version
- Target process is running.
- If remote: `gdbserver` running on target.gdb-multiarch --version || gdb --version
- 目标进程正在运行。
- 若为远程调试:目标机器上需运行`gdbserver`。Workflow
工作流程
1. Start a Session (Universal Method)
1. 启动会话(通用方法)
This method works with any agent that can run shell commands, without needing special stdin handling.
Recommended — use the helper script:
bash
./scripts/gdb_start.sh ./path/to/executable该方法适用于任何能运行shell命令的Agent,无需特殊的stdin处理。
推荐方式 — 使用辅助脚本:
bash
./scripts/gdb_start.sh ./path/to/executableCreates: gdb_cmd_pipe (named pipe), .gdb_pid (PID file), trace.log (output)
创建:gdb_cmd_pipe(命名管道)、.gdb_pid(PID文件)、trace.log(输出日志)
**Manual method** (if you need more control):
1. Create a Named Pipe (FIFO):
```bash
mkfifo gdb_cmd_pipe
```
2. Start GDB reading from the pipe:
```bash
tail -f gdb_cmd_pipe | gdb-multiarch -q -x scripts/setup.gdb --args ./executable &
echo $! > .gdb_pid
```
**Interaction Protocol:**
1. **Send Commands**: `./scripts/gdb_send.sh "command"` (or `echo "command" > gdb_cmd_pipe`)
2. **Interrupt**: `kill -INT $(cat .gdb_pid)`
3. **Resume**: `./scripts/gdb_send.sh "continue"`
**手动方法**(如需更多控制权):
1. 创建命名管道(FIFO):
```bash
mkfifo gdb_cmd_pipe
```
2. 启动GDB并从管道读取输入:
```bash
tail -f gdb_cmd_pipe | gdb-multiarch -q -x scripts/setup.gdb --args ./executable &
echo $! > .gdb_pid
```
**交互协议**:
1. **发送命令**:`./scripts/gdb_send.sh "command"`(或`echo "command" > gdb_cmd_pipe`)
2. **中断**:`kill -INT $(cat .gdb_pid)`
3. **恢复执行**:`./scripts/gdb_send.sh "continue"`2. Configure Logging (The Easy Way)
2. 配置日志(简便方法)
Use the provided to automatically configure non-blocking logging.
scripts/setup.gdbbash
undefined使用提供的自动配置非阻塞日志。
scripts/setup.gdbbash
undefinedStart GDB with the setup script
使用设置脚本启动GDB
gdb-multiarch -q -x scripts/setup.gdb -p <PID>
If you need to configure it manually (e.g., if you forgot `-x`):
```gdb
set pagination off
set logging file trace.log
set logging enabled ongdb-multiarch -q -x scripts/setup.gdb -p <PID>
若需手动配置(例如,忘记添加`-x`参数):
```gdb
set pagination off
set logging file trace.log
set logging enabled on3. Set Non-Blocking Tracepoints (dprintf
)
dprintf3. 设置非阻塞追踪点(dprintf
)
dprintfUse to print variables or status without pausing the program.
dprintfFormat:
dprintf <LOCATION>, "<FORMAT_STRING>", <ARGUMENTS>Examples:
gdb
dprintf main.c:120, "Iteration %d, Value: %s\n", i, some_string
dprintf process_request, "Got request ID: %d\n", req->idSend to let the process run while tracing:
continuegdb
continue使用打印变量或状态,而无需暂停程序。
dprintf格式:
dprintf <位置>, "<格式字符串>", <参数>示例:
gdb
dprintf main.c:120, "迭代次数 %d,值:%s\n", i, some_string
dprintf process_request, "收到请求ID:%d\n", req->id发送命令让进程在追踪的同时继续运行:
continuegdb
continue4. Conditional Tracing
4. 条件追踪
To trace only when a condition is true, use the helper script:
bash
./scripts/gdb_trace.sh loop_function '"Hit 10: %d\n", iteration' 'iteration == 10'Or manually via the pipe:
- Set the :
dprintfbash./scripts/gdb_send.sh 'dprintf loop_function, "Hit 10: %d\n", iteration' # Output in trace.log: Dprintf 2 at ... - Apply the condition. Use (GDB's convenience variable for the last breakpoint number). Important: Escape the
$bpnumso the shell doesn't expand it:$bash./scripts/gdb_send.sh 'condition $bpnum iteration == 10'
仅当条件为真时进行追踪,使用辅助脚本:
bash
./scripts/gdb_trace.sh loop_function '"触发10次:%d\n", iteration' 'iteration == 10'或通过管道手动操作:
- 设置:
dprintfbash./scripts/gdb_send.sh 'dprintf loop_function, "触发10次:%d\n", iteration' # trace.log中的输出:Dprintf 2 at ... - 应用条件。使用(GDB的便捷变量,代表最后一个断点编号)。 注意:转义
$bpnum符号,避免shell对其进行扩展:$bash./scripts/gdb_send.sh 'condition $bpnum iteration == 10'
5. Sampling the Trace
5. 采样追踪日志
Read the log file to see what's happening.
bash
tail -n 20 trace.log读取日志文件查看进程状态。
bash
tail -n 20 trace.log6. Modifying Tracepoints (The Interrupt Pattern)
6. 修改追踪点(中断模式)
Use the helper script to replace all tracepoints in one call:
bash
undefined使用辅助脚本一次性替换所有追踪点:
bash
undefinedReplaces all existing tracepoints with a new one:
将所有现有追踪点替换为新的追踪点:
./scripts/gdb_trace.sh new_func '"New trace: %d\n", x'
./scripts/gdb_trace.sh new_func '"新追踪:%d\n", x'
Or clear all tracepoints without setting new ones:
或清除所有追踪点而不设置新的:
./scripts/gdb_trace.sh --clear
**Manual method** (if you need finer control):
1. **Interrupt** — `kill -INT $(cat .gdb_pid)`
2. **Modify** — `./scripts/gdb_send.sh "delete"` then `./scripts/gdb_send.sh 'dprintf ...'`
3. **Resume** — `./scripts/gdb_send.sh "continue"`./scripts/gdb_trace.sh --clear
**手动方法**(如需更精细的控制):
1. **中断** — `kill -INT $(cat .gdb_pid)`
2. **修改** — `./scripts/gdb_send.sh "delete"` 然后 `./scripts/gdb_send.sh 'dprintf ...'`
3. **恢复执行** — `./scripts/gdb_send.sh "continue"`Helper Scripts
辅助脚本
The directory provides helper scripts that handle quoting, timing, and PID tracking.
Use these instead of raw commands — they save tokens and avoid shell quoting errors.
scripts/echo| Script | Purpose | Usage |
|---|---|---|
| Create pipe, start GDB, save PID | |
| Send a single GDB command to the pipe | |
| Interrupt + delete + set dprintf + continue | |
| Remove all tracepoints, keep running | |
| Kill processes, wait, remove session files | |
scripts/echo| 脚本 | 用途 | 使用方式 |
|---|---|---|
| 创建管道、启动GDB、保存PID | |
| 向管道发送单个GDB命令 | |
| 中断+删除+设置dprintf+恢复执行 | |
| 清除所有追踪点,保持进程运行 | |
| 终止进程、等待退出、删除会话文件 | |
Example Session
示例会话
Here is the complete workflow using the helper scripts. These are plain shell commands
that work with any agent (Cursor, Claude Code, Gemini CLI, Antigravity, Aider, etc.).
以下是使用辅助脚本的完整工作流程。这些是普通的shell命令,适用于任何Agent(Cursor、Claude Code、Gemini CLI、Antigravity、Aider等)。
1. Start GDB
1. 启动GDB
bash
./scripts/gdb_start.sh ./demo_appbash
./scripts/gdb_start.sh ./demo_appOutput: GDB started. PID=12345, pipe=gdb_cmd_pipe, log=trace.log
输出:GDB已启动。PID=12345,管道=gdb_cmd_pipe,日志=trace.log
undefinedundefined2. Set a conditional tracepoint
2. 设置条件追踪点
bash
./scripts/gdb_trace.sh loop_function '"iteration=%d\n", iteration' 'iteration == 10'bash
./scripts/gdb_trace.sh loop_function '"迭代次数=%d\n", iteration' 'iteration == 10'3. Run the program
3. 运行程序
bash
./scripts/gdb_send.sh "run"bash
./scripts/gdb_send.sh "run"4. Sample the trace
4. 采样追踪日志
bash
tail -n 20 trace.logbash
tail -n 20 trace.log5. Modify the tracepoint dynamically
5. 动态修改追踪点
bash
./scripts/gdb_trace.sh loop_function '"new trace: %d\n", iteration' 'iteration == 50'bash
./scripts/gdb_trace.sh loop_function '"新追踪:%d\n", iteration' 'iteration == 50'6. Clear all tracepoints (keep process running)
6. 清除所有追踪点(保持进程运行)
bash
./scripts/gdb_trace.sh --clearbash
./scripts/gdb_trace.sh --clear7. Stop GDB and clean up
7. 停止GDB并清理
bash
./scripts/gdb_stop.shbash
./scripts/gdb_stop.shKills GDB + target + tail feeder, waits for exit, removes session files.
终止GDB + 目标进程 + tail feeder,等待退出,删除会话文件。
undefinedundefinedAgent Compatibility
Agent兼容性
The named pipe method was designed to work with any agent that can execute shell commands.
It requires only three primitives: (1) write to a file, (2) send POSIX signals, (3) read a file.
| Agent | Shell Tool | Background Commands | Notes |
|---|---|---|---|
| Cursor | | | Stateful shell across calls |
| Claude Code | | | Stateful shell |
| Gemini CLI | Shell | | Similar to Claude Code |
| Antigravity | Shell/exec | | Varies by config |
| Aider | Shell | | May need |
Key design choice: The helper scripts (, , ) encapsulate
all quoting and timing logic, so agents don't need to reason about shell escaping or sleep intervals.
Every agent calls the same scripts the same way.
gdb_start.shgdb_send.shgdb_trace.sh命名管道方法专为任何能执行shell命令的Agent设计。
仅需三个基本操作:(1) 写入文件,(2) 发送POSIX信号,(3) 读取文件。
| Agent | Shell工具 | 后台命令 | 说明 |
|---|---|---|---|
| Cursor | | | 跨调用的有状态shell |
| Claude Code | | | 有状态shell |
| Gemini CLI | Shell | | 与Claude Code类似 |
| Antigravity | Shell/exec | | 因配置而异 |
| Aider | Shell | | 非交互式使用可能需要 |
核心设计选择:辅助脚本(、、)封装了所有引用和计时逻辑,因此Agent无需处理shell转义或睡眠间隔问题。所有Agent都以相同方式调用这些脚本。
gdb_start.shgdb_send.shgdb_trace.shLimitations
局限性
- Linux Only: This workflow relies on POSIX signals () and Linux process management. It will not work on Windows.
SIGINT - Permissions ():
ptrace- Attaching to a running process () often requires
-p PIDor adjustingsudo(set to 0)./proc/sys/kernel/yama/ptrace_scope - Workaround: Start the process via GDB () to avoid this.
--args ./exe
- Attaching to a running process (
- Signal Handling: If the target process masks , interrupting it might be difficult. You may need to use
SIGINT/kill -STOPcautiously, but that stops GDB logic too.kill -CONT - Blind Spots: Since you are not seeing in real-time (only the log file), you might miss immediate errors if you don't check the log frequently.
stdout
- 仅支持Linux:该工作流程依赖POSIX信号()和Linux进程管理。无法在Windows上运行。
SIGINT - 权限():
ptrace- 附加到运行中的进程()通常需要
-p PID权限或调整sudo(设置为0)。/proc/sys/kernel/yama/ptrace_scope - 解决方法:通过GDB启动进程()以避免此问题。
--args ./exe
- 附加到运行中的进程(
- 信号处理:若目标进程屏蔽了,可能难以中断它。你可能需要谨慎使用
SIGINT/kill -STOP,但这也会停止GDB的逻辑。kill -CONT - 盲区:由于无法实时查看(仅能查看日志文件),若不频繁检查日志,可能会错过即时错误。
stdout
Common Pitfalls
常见陷阱
These are real issues discovered in practice. Read them before starting a session.
这些是实际使用中发现的真实问题。开始会话前请仔细阅读。
1. Conditional tracepoint on a value that already passed
1. 条件追踪点设置在已过的数值上
If the program has a monotonically increasing counter (e.g., ) and you set
after the counter is already at 50, the tracepoint
will never fire. The counter will never be 20 again.
iteration++condition $bpnum iteration == 20Fix: Before setting a conditional tracepoint on a changing value, interrupt and inspect
the current value first. Then pick a target value that hasn't been reached yet.
bash
undefined如果程序有一个单调递增的计数器(例如),且你在计数器已达到50时设置,该追踪点将永远不会触发。计数器不会再回到20。
iteration++condition $bpnum iteration == 20解决方法:在变化的值上设置条件追踪点之前,先中断并检查当前值。然后选择一个尚未达到的目标值。
bash
undefinedInterrupt, check current state, then set a future target
中断,检查当前状态,然后设置未来的目标值
kill -INT $(cat .gdb_pid) && sleep 1
echo "frame 3" > gdb_cmd_pipe && sleep 0.5 # navigate to the right frame
echo "print counter" > gdb_cmd_pipe && sleep 1
tail -n 5 trace.log # read the value
kill -INT $(cat .gdb_pid) && sleep 1
echo "frame 3" > gdb_cmd_pipe && sleep 0.5 # 导航到正确的栈帧
echo "print counter" > gdb_cmd_pipe && sleep 1
tail -n 5 trace.log # 读取当前值
Now set condition for a value AHEAD of where the program is
现在为程序尚未达到的数值设置条件
undefinedundefined2. Cleanup race: removing the pipe before GDB exits
2. 清理竞争:在GDB退出前删除管道
If you delete before GDB has finished processing / commands sent
through that pipe, GDB and its child processes will linger as orphans. The pipe is gone,
so GDB can no longer read commands and the feeder also hangs.
gdb_cmd_pipekillquittail -fFix: Use which kills processes first, waits for them to die,
and only then removes session files. Never the pipe as a first step.
./scripts/gdb_stop.shrm如果在GDB处理完通过管道发送的/命令之前删除,GDB及其子进程将作为孤儿进程残留。管道已消失,因此GDB无法再读取命令, feeder也会挂起。
killquitgdb_cmd_pipetail -f解决方法:使用,它会先终止进程,等待其退出,然后再删除会话文件。切勿首先执行命令删除管道。
./scripts/gdb_stop.shrm3. Commands dropped after SIGINT
3. SIGINT后命令丢失
After sending to GDB, it needs time to stop the inferior and return to the
prompt. Commands sent too soon (e.g., 0.3s later) may be silently dropped.
kill -INT(gdb)Fix: Wait at least 1 second after SIGINT before sending the next command. The helper
scripts () already account for this.
gdb_trace.sh向GDB发送后,它需要时间停止目标进程并返回提示符。发送过早的命令(例如0.3秒后)可能会被静默丢弃。
kill -INT(gdb)解决方法:发送SIGINT后至少等待1秒再发送下一个命令。辅助脚本()已考虑到这一点。
gdb_trace.sh4. GDB cannot process commands while the inferior is running
4. 目标进程运行时GDB无法处理命令
In all-stop mode (the default), GDB blocks on the running inferior. Commands like
sent via the pipe are queued but not executed until the inferior stops.
info breakpointsFix: Always interrupt first, then send your query command, read the log, and then
. Example:
continuebash
kill -INT $(cat .gdb_pid) && sleep 1
./scripts/gdb_send.sh "info breakpoints"
sleep 1 && tail -n 10 trace.log
./scripts/gdb_send.sh "continue"在全停止模式(默认模式)下,GDB会阻塞在运行中的目标进程上。通过管道发送的等命令会排队但不会执行,直到目标进程停止。
info breakpoints解决方法:始终先中断,然后发送查询命令,读取日志,再执行。示例:
continuebash
kill -INT $(cat .gdb_pid) && sleep 1
./scripts/gdb_send.sh "info breakpoints"
sleep 1 && tail -n 10 trace.log
./scripts/gdb_send.sh "continue"5. Log output appears delayed
5. 日志输出延迟
GDB's logging () can buffer output. After a fires or a
command runs, the result may not appear in immediately.
set logging enabled ondprintftrace.logFix: Wait 1–2 seconds before reading the log after sending a command. Don't assume
the log is broken just because it looks stale — check again after a brief delay.
GDB的日志功能()可能会缓冲输出。触发或命令执行后,结果可能不会立即出现在中。
set logging enabled ondprintftrace.log解决方法:发送命令后等待1-2秒再读取日志。不要仅因为日志看起来过时就认为它损坏——短暂延迟后再次检查。
Agent Guidance (Reducing Tool Calls)
Agent使用指南(减少工具调用次数)
Follow these patterns to handle common GDB tasks in fewer round-trips.
遵循以下模式,以更少的往返次数处理常见的GDB任务。
Before setting a conditional tracepoint on a running program
在运行中的程序上设置条件追踪点之前
If the condition depends on a changing value (counter, timestamp, etc.), you MUST check
the current value first to avoid setting a condition that will never fire.
Do this in one shell call:
bash
kill -INT $(cat .gdb_pid) && sleep 1 \
&& echo "frame 3" > gdb_cmd_pipe && sleep 0.5 \
&& echo "print counter" > gdb_cmd_pipe && sleep 1 \
&& tail -n 5 trace.logThen set the tracepoint for a value ahead of the current one, and continue — again
in one call:
bash
./scripts/gdb_trace.sh loop_function '"trace: %d\n", iteration' 'iteration == <FUTURE_VALUE>'如果条件依赖于变化的值(计数器、时间戳等),你必须先检查当前值,以避免设置永远不会触发的条件。
将这些步骤合并为一次shell调用:
bash
kill -INT $(cat .gdb_pid) && sleep 1 \
&& echo "frame 3" > gdb_cmd_pipe && sleep 0.5 \
&& echo "print counter" > gdb_cmd_pipe && sleep 1 \
&& tail -n 5 trace.log然后为当前值之后的数值设置追踪点并恢复执行——同样合并为一次调用:
bash
./scripts/gdb_trace.sh loop_function '"trace: %d\n", iteration' 'iteration == <未来数值>'Setting a tracepoint and immediately running
设置追踪点并立即运行程序
When the program hasn't been started yet ( not called), you can set the tracepoint
and run in one call since there's nothing to interrupt:
runbash
./scripts/gdb_trace.sh loop_function '"iteration=%d\n", iteration' 'iteration == 10' \
&& ./scripts/gdb_send.sh "run"若程序尚未启动(未调用),你可以将设置追踪点和运行程序合并为一次调用,因为没有需要中断的内容:
runbash
./scripts/gdb_trace.sh loop_function '"iteration=%d\n", iteration' 'iteration == 10' \
&& ./scripts/gdb_send.sh "run"Sampling the log after a tracepoint
追踪点触发后采样日志
Don't check the log immediately — give the program time to reach the tracepoint.
Estimate the wait from the loop interval and current position, then combine the wait
and the read into one call:
bash
sleep 5 && tail -n 20 trace.log不要立即检查日志——给程序足够的时间到达追踪点。根据循环间隔和当前位置估算等待时间,然后将等待和读取合并为一次调用:
bash
sleep 5 && tail -n 20 trace.logInspecting state (interrupt + query + resume)
检查状态(中断+查询+恢复)
Batch all three steps into a single shell call:
bash
kill -INT $(cat .gdb_pid) && sleep 1 \
&& ./scripts/gdb_send.sh "info breakpoints" \
&& sleep 1 && tail -n 15 trace.log \
&& ./scripts/gdb_send.sh "continue"将三个步骤合并为一次shell调用:
bash
kill -INT $(cat .gdb_pid) && sleep 1 \
&& ./scripts/gdb_send.sh "info breakpoints" \
&& sleep 1 && tail -n 15 trace.log \
&& ./scripts/gdb_send.sh "continue"Shutdown and cleanup
关闭与清理
Always use the dedicated stop script — one call handles everything:
bash
./scripts/gdb_stop.sh始终使用专用的停止脚本——一次调用处理所有内容:
bash
./scripts/gdb_stop.shBest Practices
最佳实践
- Use the helper scripts instead of raw commands. They handle quoting, timing, and PID tracking.
echo - Always use if available (auto-detected by
gdb-multiarch).gdb_start.sh - Trace lightly: High-frequency tracepoints (e.g., inside tight loops) will slow down execution significantly.
- Avoid blocking commands: Never issue a GDB command that waits for user input (like without
command) unless you are sure you can provide it.end - Check frequently: Since stdout isn't visible in real-time, the log is your only window into the process.
trace.log - Clean up with : Always use the stop script instead of manually removing files. It kills processes first, avoiding orphaned GDB/tail processes.
gdb_stop.sh
- 使用辅助脚本而非原始命令。它们处理引用、计时和PID跟踪。
echo - 尽可能使用(
gdb-multiarch会自动检测)。gdb_start.sh - 轻量追踪:高频追踪点(例如在紧密循环内)会显著减慢执行速度。
- 避免阻塞命令:除非确定能提供输入,否则不要发出需要用户输入的GDB命令(如不带的
end)。command - 频繁检查:由于无法实时查看stdout,日志是你了解进程状态的唯一窗口。
trace.log - 使用清理:始终使用停止脚本而非手动删除文件。它会先终止进程,避免残留GDB/tail孤儿进程。
gdb_stop.sh