抢先一睹 Ruby 的新调试器!

2025-06-07

抢先一睹 Ruby 的新调试器!

GitHub 徽标 ruby /调试

Ruby 的调试功能

debug是 Ruby 的新调试器,将包含在 Ruby 3.1 中。由于我参与贡献和使用已经有一段时间了,我觉得是时候在它1.0正式发布之前先让大家抢先体验一下了 🙂

由于尚未正式发布,本文中提到的任何功能仍可能在发布版本中被修改/删除

更新:该项目的首席开发人员@ko1已经开始了关于调试器的博客系列。请查看😉)

介绍

正如我之前提到的,它计划成为 Ruby 3.1 的标准库。目前,你可以将其作为 gem 安装,例如:

$ gem install debug --pre
Enter fullscreen mode Exit fullscreen mode

或者

# Gemfile
# it's under active development, so I suggest using GitHub as source when possible
gem "debug", github: "ruby/debug" 
Enter fullscreen mode Exit fullscreen mode

功能上,debug类似于著名的GDB调试器和 Ruby 的byebuggem。它提供了丰富的调试命令,并具有一些独特的功能。

摘自其自述文件:

New debug.rb has several advantages:

-   Fast: No performance penalty on non-stepping mode and non-breakpoints.
-   Remote debugging: Support remote debugging natively.
    -   UNIX domain socket
    -   TCP/IP
    -   VSCode/DAP integration (VSCode rdbg Ruby Debugger - Visual Studio Marketplace)
-   Extensible: application can introduce debugging support with several ways:
    -   By `rdbg` command
    -   By loading libraries with `-r` command line option
    -   By calling Ruby's method explicitly
-   Misc
    -   Support threads (almost done) and ractors (TODO).
    -   Support suspending and entering to the console debugging with `Ctrl-C` at most of timing.
    -   Show parameters on backtrace command.
Enter fullscreen mode Exit fullscreen mode

以下是我最喜欢的功能:

  • 是彩色的。

着色示例

  • 当使用命令显示回溯时backtrace,它还会显示方法参数、块参数和返回值。
=>#0    Foo#forth_call(num1=20, num2=10) at target.rb:20 #=> 30
  #1    block {|ten=10|} in second_call at target.rb:8
Enter fullscreen mode Exit fullscreen mode
  • 可以使用脚本编写调试命令binding.break,减少手动操作。(请参阅组合部分的示例)
  • 有多个命令可以设置在不同条件下触发的断点,例如breakcatchwatch

binding.break(别名binding.b:)

如果您和pry我一样是重度用户,您可以像往常一样使用熟悉的binding.break(或只是binding.b)来启动调试会话。

binding.break实际上比更强大binding.pry,因为它可以接受命令!

例如:

  • binding.b(do: "catch CustomException")- 调试器将执行命令(catch customExeption)并继续程序。
  • binding.b(pre: "catch CustomException")- 调试器将执行命令(catch customExeption)并在该行停止。

(要执行多个命令,请使用;;作为分隔符"cmd1 ;; cmd2 ;; cmd3":)

常用命令

新的调试器有很多强大的命令。以下是我最常用的命令:

break(别名b:)

class A
  def foo; end
  def self.bar; end
end

class B < A; end
class C < A; end

B.bar
C.bar

b1 = B.new
b2 = B.new
c = C.new

b1.foo
b2.foo
c.foo
Enter fullscreen mode Exit fullscreen mode

基本用法

  • b A#foob1.foo- 当、b2.foo、 和c.foo被调用时停止
  • b A.barB.bar- 当被C.bar调用时停止
  • b B#foob1.foo- 当被b2.foo调用时停止
  • b B.barB.bar-被调用时停止
  • b b1.foob1.foo-被调用时停止

命令

  • b b1.foo do: cmdcmd- 被调用时执行b1.foo但不停止
  • b b1.foo pre: cmdcmd- 在被调用时执行b1.foo并停止

catch


class FooException < StandardError; end
class BarException < StandardError; end

def raise_foo
  raise FooException
end

def raise_bar
  raise BarException
end


raise_foo
raise_bar
Enter fullscreen mode Exit fullscreen mode
  • catch StandardErrorStandardError- 当出现任何实例时停止,包括FooExceptionBarException
  • catch FooException-FooException升起时停止

backtrace(别名bt

示例输出

=>#0    Foo#forth_call(num1=20, num2=10) at target.rb:20 #=> 30
  #1    block {|ten=10|} in second_call at target.rb:8
  #2    Foo#third_call_with_block(block=#<Proc:0x00007f9283101568 target.rb:7>) at target.rb:15
  #3    Foo#second_call(num=20) at target.rb:7
  #4    Foo#first_call at target.rb:3
  #5    <main> at target.rb:23
Enter fullscreen mode Exit fullscreen mode
  • bt- 显示堆栈上的所有帧
  • bt 10- 仅显示前 10 帧
  • bt /my_lib/- 仅显示路径匹配的帧my_lib

outline(别名ls

类似于ls中的命令irbpry

binding.b+ 命令组合

binding.b(do: "b Foo#bar do: bt")

它允许您检查方法调用的回溯,而无需触及方法定义或手动输入命令。

脚本

binding.b(do: "b Foo#bar do: bt")

class Foo
  def bar
  end
end

def some_method
  Foo.new.bar
end

some_method
Enter fullscreen mode Exit fullscreen mode

输出

DEBUGGER: Session start (pid: 75555)
[1, 10] in target.rb
=>    1| binding.b(do: "b Foo#bar do: bt")
      2|
      3| class Foo
      4|   def bar
      5|   end
      6| end
      7|
      8| def some_method
      9|   Foo.new.bar
     10| end
=>#0    <main> at target.rb:1
(rdbg:binding.break) b Foo#bar do: bt
uninitialized constant Foo
#0  BP - Method (pending)  Foo#bar do: bt
DEBUGGER:  BP - Method  Foo#bar at target.rb:4 do: bt is activated.
[1, 10] in target.rb
      1| binding.b(do: "b Foo#bar do: bt")
      2|
      3| class Foo
=>    4|   def bar
      5|   end
      6| end
      7|
      8| def some_method
      9|   Foo.new.bar
     10| end
=>#0    Foo#bar at target.rb:4
  #1    Object#some_method at target.rb:9
  # and 1 frames (use `bt' command for all frames)

Stop by #0  BP - Method  Foo#bar at target.rb:4 do: bt
(rdbg:break) bt
=>#0    Foo#bar at target.rb:4
  #1    Object#some_method at target.rb:9
  #2    <main> at target.rb:12
Enter fullscreen mode Exit fullscreen mode

binding.b(do: "b Foo#bar do: info")

它允许您在调用时检查方法的环境(例如参数):

脚本

binding.b(do: "b Foo#bar do: info")

class Foo
  def bar(a)
    a 
  end
end

def some_method
  Foo.new.bar(10)
end

some_method
Enter fullscreen mode Exit fullscreen mode

输出

DEBUGGER: Session start (pid: 75924)
[1, 10] in target.rb
=>    1| binding.b(do: "b Foo#bar do: info")
      2|
      3| class Foo
      4|   def bar(a)
      5|     a
      6|   end
      7| end
      8|
      9| def some_method
     10|   Foo.new.bar(10)
=>#0    <main> at target.rb:1
(rdbg:binding.break) b Foo#bar do: info
uninitialized constant Foo
#0  BP - Method (pending)  Foo#bar do: info
DEBUGGER:  BP - Method  Foo#bar at target.rb:4 do: info is activated.
[1, 10] in target.rb
      1| binding.b(do: "b Foo#bar do: info")
      2|
      3| class Foo
      4|   def bar(a)
=>    5|     a
      6|   end
      7| end
      8|
      9| def some_method
     10|   Foo.new.bar(10)
=>#0    Foo#bar(a=10) at target.rb:5
  #1    Object#some_method at target.rb:10
  # and 1 frames (use `bt' command for all frames)

Stop by #0  BP - Method  Foo#bar at target.rb:4 do: info
(rdbg:break) info
%self = #<Foo:0x00007fdac491c200>
a = 10
Enter fullscreen mode Exit fullscreen mode

我是一名 Rails 开发人员,因此我通常将组合代码放在控制器操作的开头,例如:

class SomeController < ApplicationController
  def index
    binding.b(pre: "b User#buggy_method do: info")
    # other code
  end
end
Enter fullscreen mode Exit fullscreen mode

然后,调试器就会执行命令并/或停在我预期的方法上。
我再也不用在多个文件之间跳转来添加binding.pryputs删除文件了😎

一个小缺点

然而,新的调试器目前还不够完美。与byebug或 不同pry,您无法在调试会话中直接评估 Ruby 表达式:

(rdbg) 1 + 1
unknown command: 1 + 1
Enter fullscreen mode Exit fullscreen mode

要评估表达式,您需要使用ppp命令:

(rdbg) p 1 + 1
=> 2
Enter fullscreen mode Exit fullscreen mode

但根据项目维护者@ko1评论,表达式求值可能会在正式1.0发布之前得到支持。

更新

随着https://github.com/ruby/debug/pull/227的合并,这个问题不再存在了

最后的想法

虽然它还没有正式发布,但我已经开始在日常工作中使用它了。我相信它很快就会成为每个 Ruby 程序员工具箱里的必备工具。所以,如果你对它的功能感兴趣,我鼓励你尝试一下 😉

文章来源:https://dev.to/st0012/a-sneak-peek-of-ruby-s-new-debugger-5caa
PREV
关于树形数据结构你需要知道的一切
NEXT
构建您自己的 Hook 来将图像上传到 Firebase 让我们开始吧