Debugging Erlang with a remote shell

8 May 2014 15:54 erlang

If you’re connected to an Erlang node via a remote shell, and you don’t have access to stdout on the original node, you’ll need to redirect the trace output to your current shell.

Now, ordinarily, you’d just do:

1> dbg:start().
** exception error: undefined function dbg:start/0

Oh. That’s not good.

This is because you’ve got an Erlang release and it doesn’t include the runtime_tools library. Assuming that you’ve got a full-blown Erlang installation on the box somewhere, you can do the following:

2> code:add_pathz("/usr/lib/erlang/lib/runtime_tools-1.8.13/ebin").

Obviously, the exact path to the runtime_tools library might vary on your box.

3> l(dbg).
4> dbg:start().

Then you can start debugging:

5> dbg:start().
6> dbg:tracer(process, {fun(Msg, _) -> io:format("~p\n", [Msg]) end, []}).

This sets up the tracer so that it calls io:format, which (by default) will send the output to your remote shell.

Then you can start adding traces:

7> dbg:tpl(my_module, some_function, '_', []).

If you want the return values:

8> dbg:tpl(another_module, some_other_function, '_', [{'_', [], [{return_trace}]}]).

Note that you can use dbg:fun2ms/1 to make that slightly more readable:

9> dbg:tpl(another_module, some_other_function, '_', dbg:fun2ms(fun(_) -> return_trace() end)).

If you want every function in a module, that’s:

10> dbg:tpl(big_module, []).

For more examples, see this Stackoverflow answer.

Make sure you tell it which processes you’re interested in:

11> dbg:p(pid(0,891,0), c).


12> dbg:p(all, c).

Do your thing; enjoy the tracing.

Then turn it off:

13> dbg:stop_clear().