检查为什么ruby脚本挂起
有时我的规格可能会挂起,我必须杀死相应的ruby进程。 当我运行用capybara和webkit驱动程序编写的集成规范时,这很常见。
是否可以检查给定的ruby过程并查看它挂在哪里? 哪种方法,操作,文件,行号等
TL;博士
使用gdb
(例如Linux):
-
echo 'call (void)rb_backtrace()' | gdb -p $(pgrep -f ruby)
或使用lldb
(例如OS X):
-
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -f ruby)
您可以使用调试库来调试Ruby脚本。
如果脚本是从shell执行的,可以通过将脚本的第一行( shebang )更改为:
#!/usr/bin/env ruby -rdebug
或者运行它:
ruby -rdebug my_script.rb
加载调试器后,您可以设置一些断点,也可以通过键入c
来继续执行来运行应用程序。
然后调试器会自动中断任何exception(例如Ctrl + C )或断点(例如组成debugger
的行)。
然后,每次显示调试器控制台时,您都可以选择:
-
c
表示继续(到下一个例外,断点或带:debugger
), -
n
代表下一行, -
w
/where
显示帧/调用堆栈, -
l
显示当前代码, -
cat
来展示捕获点。 -
h
获得更多帮助。
另请参阅: 使用ruby-debug进行调试 , ruby-debug gem的密钥快捷方式 。
这种方法的缺点是没有魔术按钮来按需提升调试器,除了在脚本中引发exception,它将显示不同的代码块而不是挂起代码。
以下是其他一些想法:
- 将
debugger
语句添加到代码中,引发调试器并逐步进行。 -
请改用Pry调试器(参见: GitHub )。
通过以下方式安装:
gem install pry
,运行方式:pry
或add asrequire 'pry'
。 -
尝试
lldb
调试器(旨在替换gdb
),它可以附加到当前正在运行的进程。示例(将
PID
替换为您的进程ID):$ lldb -p PID (lldb) bt all * thread #1: tid = 0x11d68a, 0x00007fff86c71716 libsystem_kernel.dylib`__psynch_cvwait + 10 * frame #0: 0x00007fff86c71716 libsystem_kernel.dylib`__psynch_cvwait + 10 frame #1: 0x00007fff838a9c3b libsystem_pthread.dylib`_pthread_cond_wait + 727 frame #2: 0x0000000100241aad libruby.2.0.0.dylib`native_cond_wait + 29
另一个示例显示了正在运行的ruby脚本的回溯(在其tty上):
echo 'call (void)rb_backtrace()' | lldb -p $(pgrep -f ruby)
-
或者使用
gdb
(您可以通过以下方式扩展它:gdb.rb
,它可以显示ruby对象)。- 通过以下方式安装:
sudo apt-get install gdb python-dev ncurses-dev && gem install gdb.rb
- 在Unix / OS X上,在挂起过程中按Ctrl + T来检查PID和正在做什么(或通过
ps wuax | grep ruby
检查)。 - 通过以下方式附加到进程:
gdb -p PID
。
另请参阅: 使用gdb检查挂起的ruby进程 , Ruby的GDB包装器和检查实时Ruby进程 。
- 通过以下方式安装:
- 其他可以提供帮助的库/工具包括: debugger , crash-watch , memprof , rack-perftools_profiler 。
如果没有任何帮助,您可以使用以下语法尝试: strace
(Linux)/ dtruss
(OS X):
sudo strace -fp sudo dtruss -fp
或ltrace
可以跟踪库调用而不是strace
系统调用。
如果您认为这是一个网络问题,请使用tcpdump
。
也可以看看:
- 如何调试Ruby脚本?
- 如何配置ruby以在Ctrl-C(SIGINT)上进入调试器?
- 如何使用键盘进入运行rails应用程序的ruby-debug?
- 有没有办法使用击键来调用撬ruby?
- 调试Stuck Ruby进程 – 在你杀死之前做什么-9
- 用于调试运行Ruby进程和调试Ruby工具的工具
- 调试Rails应用程序
- 在Unix上处理冻结进程的正确方法
- Sergii Boiko 在Unix中调试Ruby应用程序
- 在JumpstartLab上使用Ruby Debugger进行调试
- ruby-debug在30秒内完成(我们不需要stinkin’GUI!)
- 如何调试卡住的Ruby进程
我也有这个问题,并将其追溯到特定页面上的ShareThis javascript小部件。 你可能会或可能不会使用它,但真正的问题可能是它的悬挂,因为页面上的某些东西导致永远不会完成的外部请求。 Capybara-webkit会知道原始请求,但是如果这个代码本身发出请求,capybara-webkit永远不会知道它,如果最后一个请求挂起,说等待响应,那么capybara-webkit也将…
对于您,使用webkit-debug运行测试并查看最后一个请求。 对我来说,我看到以下内容:
1 requests remaining Page finished with true Received 200 from "http://w.sharethis.com/share4x/js/st.60709d5fdf0c137e879e64f41b8a6606.js" 0 requests remaining Started request to "http://w.sharethis.com/share4x/css/share.470030190b6a6bdc89365fcc74d3bf55.css" Received 200 from "http://w.sharethis.com/share4x/css/share.470030190b6a6bdc89365fcc74d3bf55.css" 0 requests remaining
这让我想要在我的代码库中搜索ShareThis。 我在该代码周围放了一个if(Rails.env.test?)块,瞧,我在做生意。 它是一个糟糕的解决方法,必须将测试环境的条件放入你的代码库……但它让我从这个愚蠢的问题继续前进……
希望这可以帮助。