如何调试Ruby代码?

29

我在运行Ubuntu 10.10,并想要调试一个简单的脚本。花了半天时间尝试各种方法,但最终放弃了。我应该怎么办?

我从Ubuntu软件仓库安装了ruby-dev,并执行了sudo gem install ruby-debugsudo gem install ruby-debug-ide命令。

我尝试了几种不同的方法来让这个工具工作。我尝试使用require 'ruby-debug',并在代码中某个位置设置了debugger,但Ruby无法找到ruby-debug
我尝试设置vim-ruby-debugger,它需要很长时间来执行:Rdebugger myScript.rb命令,并且允许我设置断点,但似乎没有一种方法可以使用该调试器来执行我的代码。
我还尝试使用NetBeans,但每次设置项目并点击任何东西时,它都会崩溃。

因此,亲爱的社区成员们:必须有一种方法可以调试Ruby,不是Rails,也不是复杂的脚本,只是一些CLI脚本。请帮助我,否则我就要失去剩下的理智了。

编辑: gem的执行目录不在我的路径中。所以,至少rdebug现在似乎可以使用了。


相关问题,虽然更专注于printf调试:https://dev59.com/VW865IYBdhLWcg3wKLT5 - Andrew Grimm
可能是如何调试Ruby脚本?的重复问题。 - Ciro Santilli OurBigBook.com
如果您想了解如何使用 pry-byebugpry 来暂停、检查、继续执行以及进入和退出方法,可以查看我的答案获取更加实时的回答。 - software_writer
11个回答

19

Ruby-debug适用于1.8及以上版本,ruby-debug19适用于1.9及以上版本。

ruby-debug易于学习并且非常有用。您可以告诉应用程序运行直到某个条件存在,然后让它停止,从而轻松定位nil值或其他偶发发生的条件。

在命令行中使用rdebug appname,您将进入调试器提示符。如果您想运行到第100行并停止,您可以输入c 100,调试器会设置一个临时断点,程序将运行然后停在那里,如果它在执行路径中。一旦它停止,临时断点就会被清除掉。如果您总是想在第100行停止,您可以使用b 100然后c,调试器将设置一个永久断点,继续运行,然后在达到断点时停止。您可以清除断点,设置在特定条件下出现的条件断点等。您可以键入n来跳过子例程调用并向下执行到下一条指令,或者键入s来步入它们。有各种命令以不同方式显示变量的内容,请阅读文档以获取更多信息。

从rdebug内部,您可以进入一个IRB shell,并且您的变量已经被填充,以便您可以观察它们发生了什么。从任何一个中或内部进行检查或设置值都是可以的,有助于进行假设调整。如果您在rdebug内部执行此操作,则可以使用更改后的值继续程序并查看其行为。

IRB有其存在的位置,非常适合尝试一些事情,但它不能取代调试器,就像调试器可以做一些类似IRB的事情,但无法取代它一样。两种工具的组合很好,远胜于依赖于打印语句或转储到日志文件。


Pry结合了IRB和调试器的优点,非常值得研究。


习惯于使用图形化调试器,一开始使用ruby-debug有点尴尬,但最终证明它非常实用,确实找到了我的错误。感谢这个提示! - bastibe
3
图形化调试器很漂亮,但是它们提供的功能必须存在于较低的层级下,也就是在图形界面之下,否则它们将没有任何东西可以呈现。我花了很多时间在命令行上,以至于忘记了IDE中漂亮的布局。尽管如此,我依靠命令行调试器向我展示变量中真正隐藏的内容;我对它应该是什么有自己的看法,但有时解释器会不同意我的看法 - 直到我告诉它不同为止。 :-) - the Tin Man
请查看 pry-byebug,这似乎是现在的标准。 - Hassek
我已将链接更改为pry-byebug。谢谢。 - the Tin Man

11

pry 相对于 IRB 更加优秀。以下内容来自它的 README:

Pry 是 Ruby 的标准 IRB shell 的强大替代品。它从头开始构建,提供了许多高级功能,包括:

  • 源代码浏览 (包括 pry-doc gem 中的核心 C 源代码)
  • 文档浏览
  • 实时帮助系统
  • 在编辑器中打开方法 (edit-method Class#method)
  • 语法高亮
  • 命令行集成 (从 Pry 中启动编辑器、运行 git 和 rake 等)
  • Gist 集成
  • 状态导航 (cd、ls 等)
  • 运行时调用 (将 Pry 用作开发人员控制台或调试器)
  • 异类对象支持 (BasicObject 实例、IClasses 等)
  • 强大而灵活的命令系统
  • 查看和回放历史记录的能力

  • 许多方便的命令,灵感来自 IPython、Smalltalk 和其他高级 REPL

  • 广泛的插件范围,提供远程会话、完整的调试功能等。

Pry 还旨在成为不仅仅是 IRB 的替代品;它试图将 REPL 驱动编程带到 Ruby 语言中。它目前还不如 lisp 的 SLIME 等工具强大,但这是 Pry 正朝着的方向。

Pry 也相当灵活,允许显著的用户自定义,并且很容易设置为从具有 readline 方法的任何对象中读取并写入任何具有 puts 方法的对象 - Pry 的许多其他方面也可配置,使其成为实现自定义 shell 的良好选择。


我同意,安装Ruby 1.9.3的ruby-debug让我感到很不愉快。Pry可以直接使用,非常容易上手。 - Nosh
在这里给您点个大赞。这与Python的pdb.set_trace()非常相似 - 我一直在寻找类似的东西。正如Nosh所说,它可以直接在1.9.3中运行。 - Koobz
“pry比IRB更好”这句话曾经是正确的,直到2012年中期出现了Pry.debugger - the Tin Man
1
不确定为什么人们坚持称 pry 为“调试器”——它没有开箱即用的步进、继续等支持。 - abhillman

5
  1. 在Ruby中:

    运行命令 ruby -rdebug myscript.rb

    • b :打断点
    • n(执行下一步) 或 s(逐语句) 然后 c(继续执行)
    • p(uts):用于显示
  2. 在Rails中:使用以下命令启动服务器

    • script/server --debugger

      并在代码中添加debugger。


3
我用过的最好的Ruby调试器是内置在Netbeans中的调试器。您需要从Netbeans安装快速Ruby调试器gem(我不确定它实际上是哪个gem,但Netbeans会提示您这样做)。如果您将Netbeans从内置的JRuby 1.4切换到系统默认的Ruby安装,则可以发现它工作得更好。此外,值得一看的还有breakpoint gem,并且从开发的开始就使用Ruby内置的logger库也很有帮助。祝你好运!

1
Netbeans每次我想运行它时都会崩溃。如果我的调试需求超出了ruby-debug所提供的,我肯定会去看看它。 - bastibe

1
您可以看到作弊表正在运行。
  gem install cheat
  cheat rdebug

这将显示有用的命令,以使用rdebug。

1

使用IRB。它是一个交互式的Ruby shell。当出现错误时,它会给出带有行号的跟踪信息,以便您可以知道代码的哪个部分出了问题。您可以load您的源文件并运行单个方法以查看它们是否正常工作。IRB提供有用的输出-当您输入一些代码时,它将评估表达式,然后使用.inspect打印返回值。


Pry比IRB更高效。它允许更多的灵活性,而且社区也在不断壮大(并与IRB的社区互通)。 - jackyalcine

1
调试 Ruby 代码需要两个 gem:prypry-byebug
下面是一个简单的 Ruby 脚本,它将两个数字相加并打印它们的和。请注意底部的 binding.pry 语句。此语句添加了一个断点,并告诉 Ruby 在该点停止执行。在这一点上,我们可以检查当前状态,进出方法,退出或继续执行。
require "pry"
require "pry-byebug"

class Sandbox
  def add(a, b)
    sum = a + b
    sum
  end
end

puts "Welcome to the Sandbox"

binding.pry

box = Sandbox.new
sum = box.add(3, 4)

puts "Sum = #{sum}"

如果您在终端中运行此代码,您将看到以下代码。Pry会暂停程序,终端正在等待您的输入。请注意行号旁边的箭头,它告诉您控制流程所在的位置。
➜  sandbox (main) ✗ ruby lib/sandbox.rb
Welcome to the Sandbox

From: /../sandbox/lib/sandbox.rb:15 :

    10:
    11: puts "Welcome to the Sandbox"
    12:
    13: binding.pry
    14:
 => 15: box = Sandbox.new
    16: sum = box.add(3, 4)
    17:
    18: puts "Sum = #{sum}"

[1] pry(main)>

在终端上输入next以进入下一行。
[1] pry(main)> next

From: /../sandbox/lib/sandbox.rb:16 :

    11: puts "Welcome to the Sandbox"
    12:
    13: binding.pry
    14:
    15: box = Sandbox.new
 => 16: sum = box.add(3, 4)
    17:
    18: puts "Sum = #{sum}"

[1] pry(main)>

在终端中输入“step”以进入add方法。Pry将带你进入“add”方法。
[1] pry(main)> step

From: /../sandbox/lib/sandbox.rb:6 Sandbox#add:

    5: def add(a, b)
 => 6:   sum = a + b
    7:   sum
    8: end

在调试期间,您可以通过在终端中键入“ls”或仅键入变量名称来检查本地变量。例如,键入a会显示a变量的值。
[1] pry(#<Sandbox>)> a
=> 3

在调试过程中,如果发现自己处于框架代码中,可以输入up来退出该方法,这将使您回到堆栈的上一级。我经常这样做。
[2] pry(#<Sandbox>)> up

From: /Users/akshayk/Dev/ruby/sandbox/lib/sandbox.rb:16 :

    11: puts "Welcome to the Sandbox"
    12:
    13: binding.pry
    14:
    15: box = Sandbox.new
 => 16: sum = box.add(3, 4)
    17:
    18: puts "Sum = #{sum}"

继续执行直到控制命中下一个断点,输入continue。输入exit退出调试。
如果您想随时查看当前位置,请输入@whereami,pry会显示当前断点。当您在阅读帮助文档(在调试期间在终端中键入help)或清空终端并想要查看执行位置时,可能会发现这很有帮助。
那基本上就是如何调试Ruby代码了。希望这有所帮助。
来源:如何调试Ruby代码

0

有很多基于控制台的 Ruby 调试器,具有不同的功能,根据这些功能您可以做出选择。

如果您需要的是直观的导航(例如逐行进行下一步移动、进入块),以及快速易懂的文档,则以下是最适合我的:

https://github.com/garmoshka-mo/pry-moves


我需要的另一个很酷的功能是能够从调试器内部进行调试。就像我停在控制器的操作中一样:

def index
    list = Orders.for_user(current_user) 
=>  binding.pry
end

现在我想了解为什么list是空的?- 我可以运行debug Orders.for_user(current_user)并查看发生了什么


0

Ruby调试历史悠久,许多工具仅支持MRI的特定次要版本,相当棘手。幸运的是,从2.0版本开始,您可以使用byebug

命令行用法很简单:运行byebug <your script>。您还可以编辑文件,在任何想要启动调试的位置插入byebug函数调用。


0

我喜欢使用以下内容进行测试

require "debug"; binding.break

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接