3

我想在输入 ctrl-C(或发送 SIGINT)时进入调试器。我已经安装了调试器(我正在运行 Ruby 1.9.3)并验证它可以工作。我已将此添加到我的设置文件中(这是用于 Padrino,但我认为它与 Rails 类似):

# file: config/boot.rb
Padrino.before_load do
  trap("SIGINT") { debugger } if Padrino.env == :development
end

...但键入 Ctrl-C 不会调用调试器。事实上,如果我替换debuggerputs "saw an interrupt!",键入 Ctrl-C 也不会导致打印发生。

更新

按照Mike Dunlavey的建议,我尝试从调试器中显式调用:catch Interrupt

$ rdebug `which padrino` console
^Z^Z$HOME/usr/bin/padrino:9
require 'rubygems'
(rdb:1) catch Interrupt
Catch exception Interrupt.
(rdb:1) c
=> Loading development console (Padrino v.0.10.7)
=> Loading Application BlueDotAe
=> Loading Application Admin
irb(main):001:0>   C-c C-c^C
irb(main):001:0> 

不高兴——中断没有进入调试器。

我错过了什么?

4

2 回答 2

4

如果您想在控制台中运行时捕获 SIGINT,简短的回答是:除非您对 IRB 进行猴子补丁,否则您不能。每个使用控制台的 Ruby 应用程序(无论是 padrino、rails 还是诸如此类)最终都会调用usr/lib/ruby/1.9.1/irb.rb,并且在 中IRB.start,它会:

trap("SIGINT") do
  irb.signal_handle
end

...就在进入主循环之前。这将覆盖您可能在启动代码中放入的任何陷阱(“SIGINT”)。

但是,如果您想在脚本文件中捕获 SIGINT(例如,如果您想按照Mike Dunlavey 在此处描述的那样分析您的代码),您可以创建一个脚本文件,例如:

# File: profile_complex_operation.rb
trap("SIGINT") { debugger }
MyApp.complex_operation

然后调用它,如下所示:

$ ruby profile_complex_operation.rb

现在,当您点击 ^C(或从另一个进程发送 SIGINT)时,它将进入调试器。

于 2013-03-07T20:21:40.990 回答
1

您可以尝试使用Ruby 的 GDB 包装器GitHub)。

通过以下方式在 Linux 上安装:

sudo apt-get install gdb python-dev ncurses-dev ruby-rvm
gem install gdb.rb

基本用法:

require 'gdb'

# create a new GDB::Ruby instance and attach it to
# pid 12345
gdb = GDB::Ruby.new(12345)

# print the (ruby) backtrace of the remote process
gdb.backtrace.each { |line| puts line }

# show the current local variables, and their values
p gdb.local_variables

# evaluate arbitrary ruby code in the remote process
p gdb.eval('%(pid #{$$})')

# show how many instances of each class exist in the
# remote process
p gdb.object_space

# raise an exception in the remote process
gdb.raise Exception, "go boom!"

# close the connection to the remote process
gdb.quit

或者要调试挂起的进程,请通过以下方式附加它:

rvmsudo gdb.rb PID

然后:

# in gdb get a ruby stacktrace with file names and line numbers
# here I'm filtering by files that are actually in my app dir
(gdb) ruby eval caller.select{|l| l =~ /app\//}

资料来源:使用 gdb 检查挂起的 ruby​​ 进程

一些替代方案:

  • rbtrace - 类似于 strace,但用于 ruby​​ 代码(用法:) rbtrace -p <PID> --firehose
  • tmm1(gdb.rb 的作者)的 debug.rb 脚本,它可以帮助使用 strace/gdb 调试进程。

也可以看看:

于 2015-08-01T18:16:27.030 回答