我如何调试Ruby脚本?

And*_*imm 148 ruby debugging

我从Internet复制了以下Ruby代码并进行了一些更改.

__PRE__

但它不起作用!

请帮忙.我该怎么做才能自己调试程序?

hor*_*guy 138

使用Pry(GitHub).

安装途径:

$ gem install pry
$ pry
Run Code Online (Sandbox Code Playgroud)

然后加:

require 'pry'; binding.pry
Run Code Online (Sandbox Code Playgroud)

进入你的程序.

  • 我还建议使用Pry(绝对是改变生活的人!).一旦在程序中安装并需要,设置断点就像编写`binding.pry`一样简单.它还具有颜色完成,文档查找以及动态编辑和重新加载方法的可能性. (10认同)
  • Pry的主页可在此处获取:http://pryrepl.org/. (5认同)
  • `Pry` /`byebug`很棒,但不是调试时的第一步.在大多数情况下,使用`raise object.inspect`引发异常将比打开irb会话更快地解决您的问题.我建议只使用控制台调试器再次提出异常的简单解决方案无法解决您的问题. (4认同)
  • 有没有办法用'pry`单步代码?我找不到怎么做; 这就是我对调试器的期望. (3认同)
  • @jpetazzo是的,输入'next' (2认同)

ger*_*nux 113

  1. 在Ruby中:

    ruby -rdebug myscript.rb 
    
    Run Code Online (Sandbox Code Playgroud)

    然后,

    • b <line>:放点断点
    • n(ext)s(tep)c(ontinue)
    • p(uts) 用于显示

    (比如perl调试)

  2. 在Rails中:使用启动服务器

    script/server --debugger
    
    Run Code Online (Sandbox Code Playgroud)

    并添加debugger代码.

  • -rdebug是垃圾.并且没有维护.使用Pry(参见其他答案). (6认同)
  • with -rdebug:无需更改源文件即可进行调试 (6认同)
  • @SnowCrash - 为什么你说'-r debug`是垃圾? (3认同)
  • 对于新的Ruby/Rails应用程序,Pry是正确的答案.但是我花了一个多小时试图找到一个古老版本的Pry在一个Rails 2.2应用程序上运行,并在gem要求中使用特定版本的`facets`,并且没有成功.对于古老的Rails应用程序`ruby-debug`有点讨厌但是完成了工作. (2认同)

edx*_*edx 56

作为栏杆推荐:使用撬!我只能就此达成一致.

pry是比irb更好的代表.

你需要添加

require 'pry'
Run Code Online (Sandbox Code Playgroud)

到您的源文件,然后通过添加在源代码中插入断点

binding.pry
Run Code Online (Sandbox Code Playgroud)

在您想要查看事物的地方(这就像在经典IDE环境中触发断点)

一旦你的程序击中了

binding.pry
Run Code Online (Sandbox Code Playgroud)

在你的程序的所有上下文中,你将直接进入pry repl,这样你就可以简单地探索周围的一切,调查所有对象,改变状态,甚至动态更改代码.

我相信你不能改变你当前所处方法的代码,所以你可以遗憾地不改变下一行的执行.但无论如何,好的红宝石代码往往是单行;-)


Kel*_*nan 31

调试通过提高例外容易得多不是通过眯眼print日志语句,对于大多数的错误,它通常快得多比打开了一个IRB调试像prybyebug.这些工具不应该是你的第一步.


快速调试Ruby/Rails:

1.快速方法:提高Exception当时.inspect及其结果

调试Ruby(尤其是Rails)代码的最快方法是raise在调用.inspect方法或对象时沿代码的执行路径发生异常(例如foo):

raise foo.inspect
Run Code Online (Sandbox Code Playgroud)

在上面的代码,raise触发Exception停止代码的执行,并返回一个包含方便的错误信息.inspect有关的对象/方法(即信息foo在你试图调试的线).

这种技术对于快速检查对象或方法(例如是nil吗?)以及立即确认在给定的上下文中是否甚至完全执行代码行是有用的.

2.后备:使用像或的ruby IRB调试器byebugpry

只有在获得有关代码执行流程状态的信息后,才应考虑转移到ruby gem irb调试器,pry或者byebug在哪里可以深入研究执行路径中对象的状态.


一般初学者建议

当您尝试调试问题时,总是建议: 阅读!@#$ ing错误消息(RTFM)

这意味着在行动之前仔细完整阅读错误消息,以便您了解它试图告诉您的内容. 调试时,请在阅读错误消息时按此顺序询问以下心理问题:

  1. 错误引用了哪个?(即我有正确的对象类还是我的对象nil)
  2. 错误引用了什么方法?(即它们是方法中的一个类型;我可以在这个类型/类对象上调用此方法吗?)
  3. 最后,使用我在前两个问题中可以推断的内容,我应该调查哪些代码行?(记住:堆栈跟踪中的最后一行代码不一定是问题所在.)

在堆栈跟踪中,要特别注意来自项目的代码行(例如,app/...如果您使用Rails,则以行开头).99%的时间问题出在你自己的代码上.


为了说明为什么这个顺序的解释很重要......

例如,一个令许多初学者感到困惑的Ruby错误消息:

您执行在某些时候执行的代码:

@foo = Foo.new

...

@foo.bar
Run Code Online (Sandbox Code Playgroud)

并且您收到一条错误消息:

undefined method "bar" for Nil:nilClass

初学者看到这个错误,并认为问题是该方法bar未定义的.不是.在这个错误中,重要的真实部分是:

for Nil:nilClass

for Nil:nilClass意思@foo是没有! @foo不是Foo实例变量!你有一个对象Nil.当你看到这个错误时,它只是ruby试图告诉你bar该类的对象不存在该方法Nil.(好吧!因为我们正在尝试使用一种方法来处理类的对象而Foo不是Nil).

不幸的是,由于这个错误是如何编写的(undefined method "bar" for Nil:nilClass)很容易让人误以为这个错误与bar存在有关undefined.如果没有仔细阅读,这个错误会导致初学者错误地深入研究bar方法的细节Foo,完全错过了提示该对象属于错误类的错误部分(在本例中为nil).通过完整阅读错误消息可以轻松避免这个错误.

摘要:

在开始任何调试之前,请务必仔细阅读整个错误消息.这意味着:始终检查中的错误消息类型的对象的第一,那么它的方法,开始侦探到任何堆栈跟踪或代码行,你认为该错误可能发生.那5秒钟可以为你节省5个小时的挫败感.

tl; dr:不要斜视打印日志:改为异常.在调试之前仔细阅读错误,避免兔子漏洞.

  • 尽管我同意阅读打印日志很繁琐,但我认为建议一开始不使用调试器是非常糟糕的建议。添加断点并触发它与引发异常完全相同,但是它可以为您提供应用程序当前状态的完整视图。如果检查可疑状态后还有其他问题,您可以交互式地向下钻取,而不必添加另一个异常并重新启动应用程序。 (3认同)
  • @PatrickR.根据我的经验,IRB调试器不是一个很好的第一步,当你仍然试图深入到*代码中存在问题的地方时.添加和删​​除许多IRB断点比添加异常花费更多时间,并且不会以初学者排除错误假设的异常方式给出关于代码控制流的明确答案.IRB断点也容易被遗忘,当请求挂起时会造成混淆.如果您确切地知道*问题所在并且需要调试其状态,那么请确保从IRB调试器开始.但通常情况并非如此. (2认同)

And*_*imm 20

  1. 尽可能打印出变量.(这称为printf调试)您可以通过运行来完成此操作

    STDERR.puts x.inspect
    
    Run Code Online (Sandbox Code Playgroud)

    要么

    STDERR.puts "Variable x is #{x.inspect}"
    
    Run Code Online (Sandbox Code Playgroud)

    如果你想让这更容易输入,那么你可能想要使用exemplor gem.

  2. 打开警告.如果您正在运行,ruby则使用-w开关(例如ruby -w script.rb)运行它.如果您从irb运行它,并且您在1.9.2之前使用的是ruby版本,请$VERBOSE = true在会话开始时键入.如果拼错了一个实例变量,一旦出现警告,你就会得到

    警告:实例变量@valeus未初始化

  3. 理解二进制文章的概念(以下引用来自敏捷开发人员的实践)

    将问题空间分成两半,看看哪一半包含问题.然后再将这一半分成两半,然后重复.

  4. 如果你成功使用二进制印章,你可能会发现有一行不符合你的预期.例如

    [1, 2, 3].include?([1,2])
    
    Run Code Online (Sandbox Code Playgroud)

    给出一个值false,即使你认为它会回来true.在这种情况下,您可能需要查看文档.文档的网站包括ruby-doc.orgAPIdock.在后一种情况下,你要include?在右上角附近的放大镜旁边键入,选择include?Array下面的放大镜(如果你不知道是什么类[1, 2, 3],输入[1, 2, 3].classirb),你可以包含?(数组),描述它的作用.

    但是,如果文档没有帮助,如果您可以询问特定行如何不应该做的事情,那么您更有可能得到一个好的答案,而不是为什么整个脚本没有做什么这应该.


kay*_*eck 7

删除所有的东西

欢迎来到2017 ^ _ ^

好的,所以如果您不反对尝试新的IDE,您可以免费执行以下操作.

快速说明

  1. 安装vscode
  2. 如果你还没有安装Ruby Dev Kit
  3. 为vscode安装Ruby,ruby-linter和ruby-rubocop扩展
  4. 如果需要,手动安装rubyide/vscode-ruby指定的任何gems
  5. 使用宏配置您launch.json要使用的"cwd" "program"字段{workspaceRoot}
  6. 添加一个名为的字段"showDebuggerOutput"并将其设置为true
  7. 在Debug首选项中的所有位置启用断点 "debug.allowBreakpointsEverywhere": true

详细说明

  1. 下载Visual Studio Code aka vscode; 这与Visual Studio不同.它是免费的,重量轻的,并且通常是积极的.
  2. 安装Ruby Dev Kit; 你应该按照他们的回购说明进行操作:https://github.com/oneclick/rubyinstaller/wiki/Development-Kit
  3. 接下来,您可以通过Web浏览器或IDE内部安装扩展; 这是在IDE内部.如果你选择另一个,你可以去这里.导航到vscode的Extensions部分; 您可以通过几种方式执行此操作,但最具前瞻性的方法可能会命中F1,并输入ext一个名为Extensions:Install Extensions的选项.替代品CtrlShiftx来自顶部菜单栏,View->Extensions
  4. 接下来,您将需要以下扩展名; 这些都不是100%必要的,但我会让你决定在你修改一些之后要保留什么:
    • 红宝石; 扩展作者彭吕
    • 红宝石rubocop; 扩展作者misogi
    • 红宝石棉短绒; 扩展作者Cody Hoover
  5. 在ruby脚本的目录中,我们将通过命令行调用一个目录.vscode,在那里我们只会调用一个文件launch.json,我们将在那里存储一些配置选项.
    • launch.json 内容

{ "version": "0.2.0", "configurations": [ { "name": "Debug Local File", "type":"Ruby", "request": "launch", "cwd": "${workspaceRoot}", "program": "{workspaceRoot}/../script_name.rb", "args": [], "showDebuggerOutput": true } ] }

  1. 按照扩展作者的说明进行手动gem安装.它现在位于这里:https://github.com/rubyide/vscode-ruby#install-ruby-dependencies
  2. 您可能希望能够在任何地方放置断点; 没有启用此选项会导致混淆.为此,我们将转到顶部菜单栏并选择File->Preferences->Settings(或Ctrl,)并滚动,直到您到达该Debug部分.展开它并查找一个名为的字段"debug.allowBreakpointsEverywhere"- 选择该字段并单击小铅笔图标并将其设置为true.

完成所有有趣的事情之后,您应该能够在2017年中期的类似菜单中设置断点和调试以及更暗的主题:在此输入图像描述 所有有趣的东西,如你的调用堆栈,变量查看器等.

最大的PITA是1)安装pre-reqs和2)记住配置.vscode\launch.json文件.只有#2应该将任何行李添加到未来的项目中,您只需复制一个通用的配置,就像上面列出的那样.可能有更一般的配置位置,但我不知道我的头脑.


NIA*_*NIA 6

所有其他答案已经提供了几乎所有的东西......只是一点点补充

如果你想要一些类似IDE的调试器(非CLI)并且不怕使用Vim作为编辑器,我建议使用Vim Ruby Debugger插件.

它的文档非常简单,请点击链接查看.简而言之,它允许您在编辑器中的当前行设置断点,在暂停时在漂亮的窗口中查看局部变量,逐步进入/进入 - 几乎所有常用的调试器功能.

对我来说,使用这个vim调试器调试Rails应用程序非常有趣,尽管Rails的丰富记录器功能几乎消除了对它的需求.


nur*_*tin 6

我刚发现这个宝石(将Pry变成MRI Ruby 2.0+的调试器)

https://github.com/deivid-rodriguez/pry-byebug

gem install pry-byebug
Run Code Online (Sandbox Code Playgroud)


gho*_*g74 5

  1. 您可以沿途打印变量
  2. 打开-w(警告)标志
  3. 使用ruby-debug等工具

  • 我要补充一点,`irb`是一个很好的起点.尝试使用带有可疑小块的irb.我喜欢ruby-debug(Ruby 1.9+的ruby-debug19)因为它可以很容易地停止正在运行的程序,检查变量,放入irb,然后继续运行. (2认同)

Dav*_*ira 5

我强烈推荐这个视频,以便选择适当的工具来调试我们的代码.

https://www.youtube.com/watch?v=GwgF8GcynV0

就个人而言,我将在本视频中重点介绍两个重要主题.

  • Pry非常适合调试数据,"pry是一个数据浏览器"(原文如此)
  • 调试器似乎更好地逐步调试.

那是我的两分钱!


ken*_*orb 5

要轻松调试Ruby shell脚本,只需更改其第一行:

#!/usr/bin/env ruby
Run Code Online (Sandbox Code Playgroud)

至:

#!/usr/bin/env ruby -rdebug
Run Code Online (Sandbox Code Playgroud)

然后每次显示调试器控制台时,您都可以选择:

  • cfor Continue(到下一个Exception,断点或带有:)的行debugger,
  • n 对于下一行,
  • w/ where显示帧/调用堆栈,
  • l 显示当前代码,
  • cat 显示抓点.
  • h 获得更多帮助.

另请参阅:使用ruby-debug进行调试,ruby-debug gem的密钥快捷方式.


如果脚本挂起并且您需要回溯,请尝试使用lldb/ gdblike:

echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -nf ruby)
Run Code Online (Sandbox Code Playgroud)

然后检查您的进程前景.

替换lldbgdbif工作得更好.sudo用于调试非自有进程的前缀.


Dav*_*son 5

从Ruby 2.4.0开始,在任何Ruby程序的中间启动IRB REPL会话都更加容易。将这些行放在要调试的程序中:

require 'irb'
binding.irb
Run Code Online (Sandbox Code Playgroud)

您可以运行Ruby代码并打印出局部变量。输入Ctrl + D或quit结束REPL,让Ruby程序继续运行。

您还可以在程序运行时使用putsp打印出程序中的值。