如何在 Erlang 中使用 trace 和 dbg 来调试和跟踪我的程序?
Posted
技术标签:
【中文标题】如何在 Erlang 中使用 trace 和 dbg 来调试和跟踪我的程序?【英文标题】:How to use trace and dbg in Erlang to debug and trace my program? 【发布时间】:2010-12-29 14:52:47 【问题描述】:我正在尝试开始使用erlang:trace/3
和dbg
模块来跟踪实时生产系统的行为,而无需关闭服务器。
documentation 是opaque(委婉地说),网上似乎没有任何有用的教程。
我花了一整天的时间试图通过尝试使用dbg:c
和dbg:p
对Module:Function
应用跟踪来捕获特定函数中发生的事情,但根本没有成功。
有人对如何在实时 Erlang 系统中使用 trace 有简洁的解释吗?
【问题讨论】:
github.com/massemanet/redbug 【参考方案1】:跟踪函数调用的基本步骤是在非活动节点上:
> dbg:start(). % start dbg
> dbg:tracer(). % start a simple tracer process
> dbg:tp(Module, Function, Arity, []). % specify MFA you are interested in
> dbg:p(all, c). % trace calls (c) of that MFA for all processes.
... trace here
> dbg:stop_clear(). % stop tracer and clear effect of tp and p calls.
您可以同时跟踪多个功能。通过为每个函数调用 tp
添加函数。如果要跟踪未导出的函数,则需要调用tpl
。要删除函数,请以类似方式调用ctp
或ctpl
。一些通用的 tp 调用是:
> dbg:tpl(Module, '_', []). % all calls in Module
> dbg:tpl(Module, Function, '_', []). % all calls to Module:Function with any arity.
> dbg:tpl(Module, Function, Arity, []). % all calls to Module:Function/Arity.
> dbg:tpl(M, F, A, ['_', [], [return_trace]]). % same as before, but also show return value.
最后一个参数是一个匹配规范。你可以使用dbg:fun2ms
来玩弄它。
您可以通过调用 p() 来选择要跟踪的进程。这些项目在 erlang:trace 下进行了描述。一些调用是:
> dbg:p(all, c). % trace calls to selected functions by all functions
> dbg:p(new, c). % trace calls by processes spawned from now on
> dbg:p(Pid, c). % trace calls by given process
> dbg:p(Pid, [c, m]). % trace calls and messages of a given process
我猜你永远不需要直接调用erlang:trace
,因为dbg
几乎可以为你做所有事情。
活动节点的黄金法则是只向 shell 生成一定量的跟踪输出,这样您就可以输入dbg:stop_clear().
。 :)
我经常使用一个跟踪器,它会在发生一些事件后自动停止。例如:
dbg:tracer(process, fun (_,100) -> dbg:stop_clear();
(Msg, N) -> io:format("~p~n", [Msg]), N+1 end, 0
).
如果您要在远程节点(或多个节点)上进行调试,请搜索 pan
、eper
、inviso
或 onviso
。
【讨论】:
到目前为止,我还无法跟踪将 anything 发送到 shell :( 你说这些是非活动节点上的基本步骤......大概是因为在活动节点上你只会进入 shell 滚动(并丢失)? 跟踪需要系统提供一些资源。如果您跟踪频繁发生的事件,您可能会冒着表现的风险。在最坏的情况下,你会失去联系,然后-Boom-。 在实时系统上,我会对函数调用非常具体,包括一些参数匹配。此外,大多数情况下,您可以将跟踪限制为一个进程而不是全部。 您实际上可以只使用 dbg 进行集群/远程节点调试。dbg:n(Node)
设置 Node
与您所在的节点进行相同的跟踪。【参考方案2】:
在实时系统上,我们很少追踪到 shell。 如果系统配置良好,那么它已经在收集打印到 shell 的 Erlang 日志。我不需要强调为什么这在任何实时节点中都至关重要......
让我详细说明跟踪文件:
可以跟踪到文件,这将产生一个可以在以后转换和解析的二进制输出。 (用于进一步分析或自动化控制系统等)
一个例子可以是:
跟踪打包的多个文件(12x50 MB)。在使用如此大的跟踪之前,请务必检查可用磁盘空间!
dbg:tracer(port,dbg:trace_port(file,"/log/trace",wrap,atom_to_list(node()),50000000,12)).
dbg:p(all,[call,timestamp,return_to]).
话虽如此,让我们看一下基本的跟踪命令序列:
dbg:stop_clear().
dbg:tracer().
dbg:p(all,[call, timestamp]).
dbg:tp( ... ).
dbg:tpl( ... ).
dbg:stop_clear().
您可以:
通过在 shell 中定义一些 fun()-s 添加触发器,以在给定时间或事件停止跟踪。递归 fun()-s 是实现这一目标的最佳方法,但在应用时要非常小心。
应用多种模式匹配,以确保您仅使用特定类型的参数调用特定函数调用来跟踪特定进程...
前段时间我遇到了一个问题,当我们必须检查 ETS 表的内容并且出现某个条目时,我们必须在 2-3 分钟内停止跟踪。
我还推荐 Francesco Cesarini 写的 Erlang Programming 一书。 (Erlang Programming @ Amazon)
【讨论】:
【参考方案3】:“dbg”模块是相当低级的东西。我非常使用两种技巧 经常用于我通常需要的任务。
在http://www.snookles.com/erlang/user_default.erl 使用 Erlang CLI/shell 扩展代码。它最初是由 Serge Aleynikov 写的(据我所知) 一直是一个有用的“这就是我向 shell 添加自定义函数的方式”示例。编译 模块并编辑您的 ~/.erlang 文件以指向其路径(请参阅顶部的注释 文件)。
使用EPER 实用程序集合中捆绑的“redbug”实用程序。 使用“dbg”在几秒钟内创建数百万个跟踪事件非常容易。正在做 所以在生产环境中可能是灾难性的。对于开发或生产使用, redbug 几乎不可能通过跟踪引起的过载来杀死正在运行的系统。
【讨论】:
【参考方案4】:如果您更喜欢图形跟踪器,请尝试erlyberly。它允许您选择要跟踪的函数(目前在所有进程上)并处理 dbg API。
但它不能防止过载,因此不适用于生产系统。
【讨论】:
以上是关于如何在 Erlang 中使用 trace 和 dbg 来调试和跟踪我的程序?的主要内容,如果未能解决你的问题,请参考以下文章