如何配置ruby以在Ctrl-C(SIGINT)上进入调试器?

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

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

…但是键入Ctrl-C不会调用调试器。 事实上,如果我用puts "saw an interrupt!"替换debugger puts "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> Cc Cc^C irb(main):001:0> 

没有欢乐 – 中断没有进入调试器。

我错过了什么?

如果你想在控制台中运行时捕获SIGINT,简短的答案是:除非你修补IRB,否则你不能。 每个使用控制台的Ruby应用程序(无论是padrino,rails还是whatnot)最终都会调用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)时,它将进入调试器。

您可以尝试使用GDB包装器来实现Ruby ( 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 --firehose )。
  • tmm1 (gdb.rb的作者)的debug.rb脚本,它可以帮助使用strace / gdb调试进程。

也可以看看:

  • 调试Ruby工具
  • 检查为什么ruby脚本挂起