我想在输入ctrl-C(或发送SIGINT)时输入调试器。我有installed the debugger(我正在运行Ruby 1.9.3)并验证它是否有效。我已将此添加到我的安装文件中(这适用于Padrino,但我认为它与Rails类似):
# file: config/boot.rb
Padrino.before_load do
trap("SIGINT") { debugger } if Padrino.env == :development
end
...但是输入Ctrl-C不会调用调试器。实际上,如果我将debugger
替换为puts "saw an interrupt!"
,则键入Ctrl-C也不会导致打印。
从this suggestion关注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>
没有欢乐 - 中断没有进入调试器。
我错过了什么?
答案 0 :(得分: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(例如,如果你想按照by Mike Dunlavey here描述你的代码),你可以创建一个脚本文件,如:
# File: profile_complex_operation.rb
trap("SIGINT") { debugger }
MyApp.complex_operation
然后按以下方式调用它:
$ ruby profile_complex_operation.rb
现在,当你点击^ C(或从另一个进程发送SIGINT)时,它将进入调试器。
答案 1 :(得分:1)
您可以尝试使用GDB wrapper for 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\//}
来源:Using gdb to inspect a hung ruby process
一些替代方案:
rbtrace -p <PID> --firehose
)。另见: