feat(bin/emqx): add cold_eval nodetool command
This commit is contained in:
parent
6b7d3bcf98
commit
6f99f14540
19
bin/emqx
19
bin/emqx
|
@ -14,6 +14,11 @@ ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)"
|
||||||
# shellcheck disable=SC1090
|
# shellcheck disable=SC1090
|
||||||
. "$ROOT_DIR"/releases/emqx_vars
|
. "$ROOT_DIR"/releases/emqx_vars
|
||||||
|
|
||||||
|
# defined in emqx_vars
|
||||||
|
export RUNNER_ROOT_DIR
|
||||||
|
export RUNNER_ETC_DIR
|
||||||
|
export REL_VSN
|
||||||
|
|
||||||
RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
|
RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
|
||||||
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
|
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
|
||||||
REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
|
REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
|
||||||
|
@ -109,7 +114,7 @@ relx_usage() {
|
||||||
echo " don't make it permanent"
|
echo " don't make it permanent"
|
||||||
;;
|
;;
|
||||||
*)
|
*)
|
||||||
echo "Usage: $REL_NAME {start|start_boot <file>|ertspath|foreground|stop|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|ctl|rpc|rpcterms|eval|root_dir}"
|
echo "Usage: $REL_NAME {start|start_boot <file>|ertspath|foreground|stop|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|ctl|rpc|rpcterms|eval|cold_eval|root_dir}"
|
||||||
;;
|
;;
|
||||||
esac
|
esac
|
||||||
}
|
}
|
||||||
|
@ -198,18 +203,12 @@ relx_gen_id() {
|
||||||
# Control a node
|
# Control a node
|
||||||
relx_nodetool() {
|
relx_nodetool() {
|
||||||
command="$1"; shift
|
command="$1"; shift
|
||||||
export RUNNER_ROOT_DIR
|
|
||||||
export REL_VSN
|
|
||||||
|
|
||||||
ERL_FLAGS="$ERL_FLAGS $EPMD_ARG" \
|
ERL_FLAGS="$ERL_FLAGS $EPMD_ARG" \
|
||||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
||||||
-setcookie "$COOKIE" "$command" "$@"
|
-setcookie "$COOKIE" "$command" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
call_hocon() {
|
call_hocon() {
|
||||||
export RUNNER_ROOT_DIR
|
|
||||||
export RUNNER_ETC_DIR
|
|
||||||
export REL_VSN
|
|
||||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" hocon "$@" \
|
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" hocon "$@" \
|
||||||
|| die "call_hocon_failed: $*" $?
|
|| die "call_hocon_failed: $*" $?
|
||||||
}
|
}
|
||||||
|
@ -217,8 +216,6 @@ call_hocon() {
|
||||||
# Run an escript in the node's environment
|
# Run an escript in the node's environment
|
||||||
relx_escript() {
|
relx_escript() {
|
||||||
shift; scriptpath="$1"; shift
|
shift; scriptpath="$1"; shift
|
||||||
export RUNNER_ROOT_DIR
|
|
||||||
|
|
||||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
|
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -709,6 +706,10 @@ case "$1" in
|
||||||
shift
|
shift
|
||||||
relx_nodetool "eval" "$@"
|
relx_nodetool "eval" "$@"
|
||||||
;;
|
;;
|
||||||
|
cold_eval)
|
||||||
|
shift;
|
||||||
|
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" cold_eval "$@"
|
||||||
|
;;
|
||||||
*)
|
*)
|
||||||
relx_usage "$1"
|
relx_usage "$1"
|
||||||
exit 1
|
exit 1
|
||||||
|
|
63
bin/nodetool
63
bin/nodetool
|
@ -24,6 +24,8 @@ main(Args) ->
|
||||||
["hocon" | Rest] ->
|
["hocon" | Rest] ->
|
||||||
%% forward the call to hocon_cli
|
%% forward the call to hocon_cli
|
||||||
hocon_cli:main(Rest);
|
hocon_cli:main(Rest);
|
||||||
|
["cold_eval" | Rest] ->
|
||||||
|
code_eval(Rest);
|
||||||
_ ->
|
_ ->
|
||||||
do(Args)
|
do(Args)
|
||||||
end.
|
end.
|
||||||
|
@ -117,40 +119,53 @@ do(Args) ->
|
||||||
io:format("~p\n", [Other])
|
io:format("~p\n", [Other])
|
||||||
end;
|
end;
|
||||||
["eval" | ListOfArgs] ->
|
["eval" | ListOfArgs] ->
|
||||||
% shells may process args into more than one, and end up stripping
|
Parsed = parse_eval_args(ListOfArgs),
|
||||||
% spaces, so this converts all of that to a single string to parse
|
|
||||||
String = binary_to_list(
|
|
||||||
list_to_binary(
|
|
||||||
join(ListOfArgs," ")
|
|
||||||
)
|
|
||||||
),
|
|
||||||
|
|
||||||
% then just as a convenience to users, if they forgot a trailing
|
|
||||||
% '.' add it for them.
|
|
||||||
Normalized =
|
|
||||||
case lists:reverse(String) of
|
|
||||||
[$. | _] -> String;
|
|
||||||
R -> lists:reverse([$. | R])
|
|
||||||
end,
|
|
||||||
|
|
||||||
% then scan and parse the string
|
|
||||||
{ok, Scanned, _} = erl_scan:string(Normalized),
|
|
||||||
{ok, Parsed } = erl_parse:parse_exprs(Scanned),
|
|
||||||
|
|
||||||
% and evaluate it on the remote node
|
% and evaluate it on the remote node
|
||||||
case rpc:call(TargetNode, erl_eval, exprs, [Parsed, [] ]) of
|
case rpc:call(TargetNode, erl_eval, exprs, [Parsed, [] ]) of
|
||||||
{value, Value, _} ->
|
{value, Value, _} ->
|
||||||
io:format ("~p\n",[Value]);
|
io:format ("~p~n",[Value]);
|
||||||
{badrpc, Reason} ->
|
{badrpc, Reason} ->
|
||||||
io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
|
io:format("RPC to ~p failed: ~p~n", [TargetNode, Reason]),
|
||||||
halt(1)
|
halt(1)
|
||||||
end;
|
end;
|
||||||
Other ->
|
Other ->
|
||||||
io:format("Other: ~p\n", [Other]),
|
io:format("Other: ~p~n", [Other]),
|
||||||
io:format("Usage: nodetool {genconfig, chkconfig|getpid|ping|stop|rpc|rpc_infinity|rpcterms|eval [Terms]} [RPC]\n")
|
io:format("Usage: nodetool chkconfig|getpid|ping|stop|rpc|rpc_infinity|rpcterms|eval|cold_eval [Terms] [RPC]\n")
|
||||||
end,
|
end,
|
||||||
net_kernel:stop().
|
net_kernel:stop().
|
||||||
|
|
||||||
|
code_eval(Args) ->
|
||||||
|
Parsed = parse_eval_args(Args),
|
||||||
|
case erl_eval:exprs(Parsed, []) of
|
||||||
|
{value, Value, _} ->
|
||||||
|
io:format ("~p~n", [Value]);
|
||||||
|
Other ->
|
||||||
|
io:format("cold_eval_failed_with: ~p~n", [Other]),
|
||||||
|
halt(1)
|
||||||
|
end.
|
||||||
|
|
||||||
|
parse_eval_args(Args) ->
|
||||||
|
% shells may process args into more than one, and end up stripping
|
||||||
|
% spaces, so this converts all of that to a single string to parse
|
||||||
|
String = binary_to_list(
|
||||||
|
list_to_binary(
|
||||||
|
join(Args," ")
|
||||||
|
)
|
||||||
|
),
|
||||||
|
|
||||||
|
% then just as a convenience to users, if they forgot a trailing
|
||||||
|
% '.' add it for them.
|
||||||
|
Normalized =
|
||||||
|
case lists:reverse(String) of
|
||||||
|
[$. | _] -> String;
|
||||||
|
R -> lists:reverse([$. | R])
|
||||||
|
end,
|
||||||
|
|
||||||
|
% then scan and parse the string
|
||||||
|
{ok, Scanned, _} = erl_scan:string(Normalized),
|
||||||
|
{ok, Parsed } = erl_parse:parse_exprs(Scanned),
|
||||||
|
Parsed.
|
||||||
|
|
||||||
do_with_ret(Args, Name, Handler) ->
|
do_with_ret(Args, Name, Handler) ->
|
||||||
{arity, Arity} = erlang:fun_info(Handler, arity),
|
{arity, Arity} = erlang:fun_info(Handler, arity),
|
||||||
case take_args(Args, Name, Arity) of
|
case take_args(Args, Name, Arity) of
|
||||||
|
|
Loading…
Reference in New Issue