nodetool 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138
  1. %% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
  2. %% ex: ft=erlang ts=4 sw=4 et
  3. %% -------------------------------------------------------------------
  4. %%
  5. %% nodetool: Helper Script for interacting with live nodes
  6. %%
  7. %% -------------------------------------------------------------------
  8. main(Args) ->
  9. ok = start_epmd(),
  10. %% Extract the args
  11. {RestArgs, TargetNode} = process_args(Args, [], undefined),
  12. %% See if the node is currently running -- if it's not, we'll bail
  13. case {net_kernel:hidden_connect_node(TargetNode), net_adm:ping(TargetNode)} of
  14. {true, pong} ->
  15. ok;
  16. {_, pang} ->
  17. io:format("Node ~p not responding to pings.\n", [TargetNode]),
  18. halt(1)
  19. end,
  20. case RestArgs of
  21. ["ping"] ->
  22. %% If we got this far, the node already responsed to a ping, so just dump
  23. %% a "pong"
  24. io:format("pong\n");
  25. ["stop"] ->
  26. io:format("~p\n", [rpc:call(TargetNode, init, stop, [], 60000)]);
  27. ["restart"] ->
  28. io:format("~p\n", [rpc:call(TargetNode, init, restart, [], 60000)]);
  29. ["reboot"] ->
  30. io:format("~p\n", [rpc:call(TargetNode, init, reboot, [], 60000)]);
  31. ["rpc", Module, Function | RpcArgs] ->
  32. case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
  33. [RpcArgs], 60000) of
  34. ok ->
  35. ok;
  36. {badrpc, Reason} ->
  37. io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
  38. halt(1);
  39. _ ->
  40. halt(1)
  41. end;
  42. ["rpcterms", Module, Function, ArgsAsString] ->
  43. case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
  44. consult(ArgsAsString), 60000) of
  45. {badrpc, Reason} ->
  46. io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
  47. halt(1);
  48. Other ->
  49. io:format("~p\n", [Other])
  50. end;
  51. Other ->
  52. io:format("Other: ~p\n", [Other]),
  53. io:format("Usage: nodetool {ping|stop|restart|reboot}\n")
  54. end,
  55. net_kernel:stop().
  56. process_args([], Acc, TargetNode) ->
  57. {lists:reverse(Acc), TargetNode};
  58. process_args(["-setcookie", Cookie | Rest], Acc, TargetNode) ->
  59. erlang:set_cookie(node(), list_to_atom(Cookie)),
  60. process_args(Rest, Acc, TargetNode);
  61. process_args(["-name", TargetName | Rest], Acc, _) ->
  62. ThisNode = append_node_suffix(TargetName, "_maint_"),
  63. {ok, _} = net_kernel:start([ThisNode, longnames]),
  64. process_args(Rest, Acc, nodename(TargetName));
  65. process_args(["-sname", TargetName | Rest], Acc, _) ->
  66. ThisNode = append_node_suffix(TargetName, "_maint_"),
  67. {ok, _} = net_kernel:start([ThisNode, shortnames]),
  68. process_args(Rest, Acc, nodename(TargetName));
  69. process_args([Arg | Rest], Acc, Opts) ->
  70. process_args(Rest, [Arg | Acc], Opts).
  71. start_epmd() ->
  72. [] = os:cmd(epmd_path() ++ " -daemon"),
  73. ok.
  74. epmd_path() ->
  75. ErtsBinDir = filename:dirname(escript:script_name()),
  76. Name = "epmd",
  77. case os:find_executable(Name, ErtsBinDir) of
  78. false ->
  79. case os:find_executable(Name) of
  80. false ->
  81. io:format("Could not find epmd.~n"),
  82. halt(1);
  83. GlobalEpmd ->
  84. GlobalEpmd
  85. end;
  86. Epmd ->
  87. Epmd
  88. end.
  89. nodename(Name) ->
  90. case string:tokens(Name, "@") of
  91. [_Node, _Host] ->
  92. list_to_atom(Name);
  93. [Node] ->
  94. [_, Host] = string:tokens(atom_to_list(node()), "@"),
  95. list_to_atom(lists:concat([Node, "@", Host]))
  96. end.
  97. append_node_suffix(Name, Suffix) ->
  98. case string:tokens(Name, "@") of
  99. [Node, Host] ->
  100. list_to_atom(lists:concat([Node, Suffix, os:getpid(), "@", Host]));
  101. [Node] ->
  102. list_to_atom(lists:concat([Node, Suffix, os:getpid()]))
  103. end.
  104. %%
  105. %% Given a string or binary, parse it into a list of terms, ala file:consult/0
  106. %%
  107. consult(Str) when is_list(Str) ->
  108. consult([], Str, []);
  109. consult(Bin) when is_binary(Bin)->
  110. consult([], binary_to_list(Bin), []).
  111. consult(Cont, Str, Acc) ->
  112. case erl_scan:tokens(Cont, Str, 0) of
  113. {done, Result, Remaining} ->
  114. case Result of
  115. {ok, Tokens, _} ->
  116. {ok, Term} = erl_parse:parse_term(Tokens),
  117. consult([], Remaining, [Term | Acc]);
  118. {eof, _Other} ->
  119. lists:reverse(Acc);
  120. {error, Info, _} ->
  121. {error, Info}
  122. end;
  123. {more, Cont1} ->
  124. consult(Cont1, eof, Acc)
  125. end.