ectl
is an escript command-line interface for some useful debugging and profiling tools for erlang VM, redbug and recon are currently supported.
$ ./ectl
Usage: ectl <command> [<arg>] [options]
-h, --help Print this help.
-v, --version Print the version and exit.
Available subcommands:
proc_info
proc_hog
proc_win
sysinfos
proc_state
redbug
ping
sysinfo
For help on any individual command run `ectl COMMAND -h`
To use ectl
, you need erlang R15B03 or later.
To build ectl
, just clone and run:
make
then you will have an executable ectl
script in the folder.
redbug is similar to the OTP dbg application, but safer, better etc. ectl
wraps this great tool in a nicer cli interface.
$ ./ectl redbug -h
Usage: ectl redbug <node> <trace_pattern> [options]
-c, --cookie Erlang cookie to use
-t, --time stop trace after this many ms [default: 15000]
-m, --msgs stop trace after this many msgs [default: 10]
-p, --proc Erlang process all|pid()|atom(RegName) [default: all]
To trace calls of erlang:memory/0
on my_app@127.0.0.1
for 10 seconds, run:
$ ./ectl redbug my_app@127.0.0.1 "erlang:memory() -> return" -c my_app
11:22:07 <{erlang,apply,2}> {erlang,memory,[]}
11:22:07 <{erlang,apply,2}> {erlang,memory,0} -> [{total,15072488},
{processes,2804020},
{processes_used,2804020},
{system,12268468},
{atom,339441},
{atom_used,322103},
{binary,598616},
{code,7314528},
{ets,529432}]
Ping one or more nodes in your cluster.
$ ./ectl ping -h
Usage: ectl ping <node> [...] [options]
-c, --cookie Erlang cookie to use
-o, --output output format: table|json|plain [default: plain]
$ ./ectl ping my_app1@127.0.0.1 my_app2@127.0.01 -c my_app
┌─────────────────────┬────────┐
│ node │ result │
├─────────────────────┼────────┤
│ my_app1@127.0.0.1 │ pong │
├─────────────────────┼────────┤
│ my_app2@127.0.01 │ pang │
└─────────────────────┴────────┘
Use recon:node_stats_list/2 to get system of a node.
$ ./ectl sysinfo -h
Usage: ectl sysinfo <node> [options]
-c, --cookie Erlang cookie to use
-o, --output output format: table|json|plain [default: plain]
-n, --num N time to sample stats [default: 5]
-i, --interval wait time for each sample [default: 1]
$ ./ectl sysinfo my_app@127.0.0.1 -c my_app
bytes_in bytes_out err_log_q gc_cnt gc_reclaimed mem_atom mem_bin mem_ets mem_procs mem_total proc_cnt reds runq
0 0 0 2 2251 353694 124112 533288 2927706 14875648 91 5681 0
16619 16589 0 81 180749 353694 114424 533288 2990802 14929096 90 63926 0
23146 20215 0 104 239930 353694 116448 533288 3000946 14941240 90 94567 0
15782 16589 0 83 208024 353694 114584 533288 3005842 14944296 90 66224 0
9591 9290 0 43 77911 353694 114664 533288 2998714 14937008 90 36095 0
Same with sysinfo, but get info from multiple nodes.
$ ./ectl sysinfos -h
Usage: ectl sysinfos <node> [...] [options]
-c, --cookie Erlang cookie to use
-o, --output output format: table|json|plain [default: plain]
$ ./ectl sysinfos my_app1@127.0.0.1 my_app2@127.0.0.1 -c my_app
bytes_in bytes_out err_log_q gc_cnt gc_reclaimed mem_atom mem_bin mem_ets mem_procs mem_total proc_cnt reds runq
0 0 0 2 1545 354225 163272 535208 3028214 15090232 92 5667 0
0 0 0 1 88 350697 192992 789744 4538468 17817872 169 887 0
Use recon:info/1 to get info of a process of a node.
$ ./ectl proc_info -h
Usage: ectl proc_info <node> <pid> [options]
-c, --cookie Erlang cookie to use
$ ./ectl proc_info my_app@127.0.0.1 0.79.0 -c my_app
============= meta =============
initial_call {proc_lib,init_p,5}
registered_name cowboy_clock
group_leader <5956.76.0>
status waiting
============= dictionary =============
$ancestors [cowboy_sup,<5956.77.0>]
$initial_call {cowboy_clock,init,1}
============= stacktrace =============
mod fun arity file line
gen_server loop 6 gen_server.erl 358
proc_lib init_p_do_apply 3 proc_lib.erl 227
============= memory =============
memory 24712
message_queue_len 0
heap_size 2584
total_heap_size 2961
============= garbage collection =============
min_bin_vheap_size 46368
min_heap_size 233
fullsweep_after 65535
minor_gcs 3350
============= works =============
reductions 627628
Use recon:get_state/1 to get state of a process.
$ ./ectl proc_state -h
Usage: ectl proc_state <node> <pid> [options]
-c, --cookie Erlang cookie to use
$ ./ectl proc_state my_app@127.0.0.1 0.79.0 -c my_app
{state,{{2013,9,29},{3,43,0}},
<<"Sun, 29 Sep 2013 03:43:00 GMT">>,
{interval,#Ref<5944.0.0.102>}}
Use recon:proc_count/2 to get process hog, like memory hog.
$ ./ectl proc_hog -h
Usage: ectl proc_hog <node> <attr> [options]
-c, --cookie Erlang cookie to use
-n, --num number of results [default: 10]
$ ./ectl proc_hog my_app@127.0.0.1 memory -c my_app
pid name val current_function initial_call
<5948.109.0> sync_scanner 1801584 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.25.0> code_server 284360 {code_server,loop,1} {erlang,apply,2}
<5948.32.0> 142752 {shell,get_command1,5} {erlang,apply,2}
<5948.3.0> erl_prim_loader 142608 {erl_prim_loader,loop,3} {erlang,apply,2}
<5948.7.0> application_controller 88952 {gen_server,loop,6} {erlang,apply,2}
<5948.24.0> file_server_2 75816 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.91.0> 55040 {application_master,loop_it,4} {application_master,start_it,4}
<5948.11.0> kernel_sup 34872 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.6.0> error_logger 29632 {gen_event,fetch_msg,5} {proc_lib,init_p,5}
<5948.112.0> sync_options 29552 {gen_server,loop,6} {proc_lib,init_p,5}
Use recon:proc_window/3 to sample process info in a give timespan.
$ ./ectl proc_win -h
Usage: ectl proc_win <node> [options]
-c, --cookie Erlang cookie to use
-t, --time seconds to sample [default: 10000]
-n, --num number of results [default: 10]
-a, --attr attritube to sample [default: memory]
$ ./ectl proc_win my_app@127.0.0.1 -c my_app
pid name val current_function initial_call
<5948.13.0> global_name_server 7896 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.24117.1> 2704 {global,resolver,2} {erlang,apply,2}
<5948.18.0> erl_epmd 0 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.50.0> 0 {application_master,main_loop,2} {proc_lib,init_p,5}
<5948.82.0> 0 {application_master,main_loop,2} {proc_lib,init_p,5}
<5948.33.0> 0 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.65.0> 0 {application_master,main_loop,2} {proc_lib,init_p,5}
<5948.97.0> 0 {gen_server,loop,6} {proc_lib,init_p,5}
<5948.24115.1> 0 {dist_util,con_loop,9} {inet_tcp_dist,do_accept,6}
<5948.16.0> inet_db 0 {gen_server,loop,6} {proc_lib,init_p,5}