為什麼需要 Attach#

有時你好不容易重現了一個難以捉摸的 bug,但程式並不是從 debugger 中啟動的,要再次重現也很困難。Debugger 提供了附加到正在執行程序的能力,讓你可以在問題發生時立即介入。

Native 程式的 Attach#

gdb#

先用 ps 指令找到目標程序的 PID:

$ ps -u apache
  PID TTY     TIME CMD
25582 ?    00:00:00 httpd

$ sudo gdb -p 25582
(gdb) where

gdb 會附加到該程序並暫停執行,你可以立即查看 call stack。

Visual Studio#

使用 Debug - Attach to Process 指令。

Java 程式的 Attach#

要讓 Java 程式接受 debugger 連線,需要在啟動 JVM 時加入 JDWP agent 參數:

-agentlib:jdwp=transport=dt_socket,address=127.0.0.1:8000,server=y,suspend=n

然後在 Eclipse 中透過 Run - Debug Configurations - New launch configuration 設定 Host 和 Port,點擊 Debug 即可連線。

如果只是要快速了解一個行為異常的 Java 程序正在做什麼,可以用 jstack 指令加上 PID,它會顯示所有執行中 thread 的 stack dump。

Attach 後可以做什麼#

  • 暫停程序 — Eclipse: Run - Suspend、Visual Studio: Debug - Break All、gdb: break
  • 檢查 call stack 了解程式正在執行什麼
  • 設定 breakpoints 等待特定程式碼被執行
  • 檢查全域變數與物件

遠端除錯(Remote Debugging)#

當程式執行在另一台機器上(嵌入式裝置、無 GUI 的 server),可以透過 remote debugging:

  1. 在遠端機器上啟動 debug server:

    $ gdbserver your-workstation.example.com:1234 video-recorder
  2. 在本地工作站用 gdb 連線:

    $ gdb video-recorder
    (gdb) target remote tv-12.example.com:1234

之後就可以像本地除錯一樣操作。

如果覺得 remote debugging 的設定太複雜,也可以考慮在遠端機器上安裝 GUI debugger,然後透過 X forwarding 或螢幕鏡像來操作。

重點回顧#

  • 透過 attach 功能,可以除錯已經在執行中的程序,不需要重新啟動
  • remote debugging 除錯資源受限或無 GUI 的遠端裝置上的程式