如何调试无法启动的 erlang 应用程序

nia*_*hoo 5 debugging erlang erlang-otp erlang-shell

如果我编写了一些 erlang 代码来构建一个监督树,然后使用以下命令在引导时启动应用程序,可能很难找出为什么它不起作用:

erl -s myapp -pa ebin ... ...
Run Code Online (Sandbox Code Playgroud)

(myapp 示例模块)

-module(myapp).
-export([start/0]).
start() -> application:start(myapp).
Run Code Online (Sandbox Code Playgroud)

假设我的应用程序启动了一个主管 myapp_sup。myapp_sup 轮流启动几个主管(假设 server_sup、database_sup、another_sup)。

这些主管将启动一些 gen_servers。

在某些时候,如果我的代码中有错误,我找不到它!

我在某个 gen_server 的 init 回调中写了一个对 somemodule:functionthatdoesntexists() 的调用。

所有 vm 说的是“init 在 do boot 中终止”,然后显示错误匹配的错误位置,精确文件和我的顶级模块 (myapp) 的行。

(不匹配,因为 ok = application:start(...) 将不匹配)。

我查看了 erl_crash.dump 文件,没有关于这个未定义函数的信息(但我在原子列表中找到了它)。

所以,我写了一些日志来大致查看错误在哪里,但是我必须手动启动我的 gen_servers 以获取正确的错误信息。

我错过了什么,我怎么能更快地弄清楚?

谢谢

Ste*_*ski 2

如果您的应用程序调用未知模块,您的erl_crash.dump文件将包含如下行:

41DABB8:t4:A8:nonexistent_module,A7:unknown,N,N
Run Code Online (Sandbox Code Playgroud)

nonexistent_module其中该行中的“未知”表示找不到该模块。在这些情况下,在文件中搜索erl_crash.dump字符串“unknown”会有所帮助。

如果您怀疑某个模块调用了不存在的函数,您可以使用交互式 erl shell 中的xref 工具找到它。确保使用调试信息编译模块(通常通过erlc +debug_info),然后:

1> xref:m(my_module).
[{deprecated,[]},
 {undefined,[{{my_module,init,1},{another_module,unknown,0}}]},
 {unused,[]}]
Run Code Online (Sandbox Code Playgroud)

这里,向xref我们展示了该my_module:init/1函数调用了该another_module:unknown/0函数,但该unknown/0函数未在another_module.

您还可以用来xref检查整个应用程序;详细信息请参阅文档