如何调试无法启动的erlang应用程序
Posted
技术标签:
【中文标题】如何调试无法启动的erlang应用程序【英文标题】:How to debug an erlang application that won't boot 【发布时间】:2013-01-08 21:32:49 【问题描述】:如果我编写一些 erlang 代码来构建监督树,然后在启动时使用以下命令启动应用程序,可能很难找出它为什么不起作用:
erl -s myapp -pa ebin ... ...
(myapp 示例模块)
-module(myapp).
-export([start/0]).
start() -> application:start(myapp).
假设我的应用启动了主管 myapp_sup。 myapp_sup 轮流启动多个主管(比如说 server_sup、database_sup、another_sup)。
这些主管将启动一些 gen_servers。
在某些时候,如果我的代码有错误,我找不到它!
我在一些 gen_server 的 init 回调中写了一个对 somemodule:functionthatdoesntexists() 的调用。
所有 vm 都说“init terminating in do boot”,然后显示错误匹配的错误位置、精确文件和我的***模块 (myapp) 的行。
(不匹配,因为 ok = application:start(...) 将不匹配)。
我查看了 th erl_crash.dump 文件,没有关于这个未定义函数的信息(但我在原子列表中找到了它)。
所以,我写了一些日志来大致查看错误在哪里,但是我必须手动启动我的 gen_servers 以获取正确的错误信息。
我错过了什么,我怎样才能更快地弄清楚?
谢谢
【问题讨论】:
【参考方案1】:如果您的应用程序调用未知模块,您的erl_crash.dump
文件将包含如下一行:
41DABB8:t4:A8:nonexistent_module,A7:unknown,N,N
行中的“unknown”表示找不到模块nonexistent_module
。在这些情况下,在您的 erl_crash.dump
文件中搜索字符串“unknown”会有所帮助。
如果您怀疑某个模块调用了一个不存在的函数,您可以在交互式 erl shell 中使用the xref tool 找到它。确保使用调试信息(通常通过erlc +debug_info
)编译模块,然后:
1> xref:m(my_module).
[deprecated,[],
undefined,[my_module,init,1,another_module,unknown,0],
unused,[]]
这里,xref
向我们展示了my_module:init/1
函数调用了another_module:unknown/0
函数,但unknown/0
函数未在another_module
中定义。
您也可以使用xref
来检查整个应用程序;详情见the documentation
【讨论】:
感谢您的回答。但我没有和你一样的输出。既不是不存在的模块,也不是实际模块中不存在的功能。我已将外部参照添加到我的生成文件中,使用钢筋很容易,谢谢。但是问题仍然存在,假设我拼错了数据库监听的端口......问题是你不知道大部分时间你正在寻找的错误是什么。 我上面显示的输出是使用 Erlang/OTP R15B03 (erts 5.9.3.1) 获得的;也许你的版本不同。 您还应该考虑为您的模块实施单元测试,因为它们可以很好地发现诸如拼写错误的原子或其他名称等问题。 相同的版本,不同的配置我想。你说得对,我真的应该去 TDD。我在 Erlang 中不习惯,我会尝试一下。 这几天我开发了一个小型应用程序,我从 eunit 开始。在测试期间,Eunit 不会因为晦涩的消息而失败,而是会为我提供发生错误的确切代码行。这是非常好的。再次感谢。【参考方案2】:将 -init_debug 添加到您的 erl 命令中:)
【讨论】:
谢谢,但这并不能解决问题:来自用户代码的错误不会在引导顺序中发生。他们紧随其后。使用“-init_debug”没有关于我的 undef 函数的更多信息。以上是关于如何调试无法启动的erlang应用程序的主要内容,如果未能解决你的问题,请参考以下文章
Erlang/Yaws:无法使用 .conf 文件在应用程序中启动 Web 服务器
RabbitMQ无法启动,TCP连接成功但Erlang分发失败