-module(server_control_main).
|
|
|
|
-export([start/0]).
|
|
|
|
-define(RPC_TIMEOUT, infinity).
|
|
|
|
commands_desc() ->
|
|
[{"stop", "停止游戏服务器进程"},
|
|
{"stop_all", "停止游戏集群进程"},
|
|
{"stop_app", "关闭server application"},
|
|
{"start_app", "打开server application"},
|
|
{"cluster_status", "集群状态"}].
|
|
opt_spec_list() ->
|
|
Node = case get(nodename) of
|
|
undefined ->
|
|
throw(not_nodename);
|
|
V ->
|
|
V
|
|
end,
|
|
[
|
|
{help, $h, "help", undefined, "显示帮助,然后退出"},
|
|
{node, undefined, "node", {atom, Node}, "管理节点"}
|
|
].
|
|
usage() ->
|
|
getopt:usage(opt_spec_list(), "server_ctl", "<command> [<args>]", commands_desc()),
|
|
err_misc:quit(1).
|
|
parse_arguments(CmdLine) ->
|
|
case getopt:parse(opt_spec_list(), CmdLine) of
|
|
{ok, {Opts, [Command | Args]}} ->
|
|
{ok, {list_to_atom(Command), Opts, Args}};
|
|
{ok, {_Opts, []}} ->
|
|
no_command;
|
|
Error ->
|
|
io:format("Error ~p~n", [Error]),
|
|
no_command
|
|
end.
|
|
|
|
start() ->
|
|
{ok, [[NodeStr|_]|_]} = init:get_argument(nodename),
|
|
put(nodename, list_to_atom(NodeStr)),
|
|
{Command, Opts, Args} =
|
|
case parse_arguments(init:get_plain_arguments()) of
|
|
{ok, Res} ->
|
|
Res;
|
|
no_command ->
|
|
usage()
|
|
end,
|
|
Node = proplists:get_value(node, Opts),
|
|
net_adm:ping(Node),
|
|
timer:sleep(1000), %% wait auto find node
|
|
%% The reason we don't use a try/catch here is that rpc:call turns
|
|
%% thrown errors into normal return values
|
|
% io:format("Opts ~p~n", [Opts]),
|
|
case catch action(Command, Node, Args, Opts) of
|
|
ok ->
|
|
io:format("done.~n", []),
|
|
quit(0);
|
|
{ok, Info} ->
|
|
io:format("done (~p).~n", [Info]),
|
|
quit(0);
|
|
Other ->
|
|
io:format("other result ~p~n", [Other]),
|
|
quit(2)
|
|
end.
|
|
|
|
action(info, Node, _Args, _Opts) ->
|
|
io:format("System info for Node ~p~n", [Node]),
|
|
Res = call(Node, {main, get_info, []}),
|
|
io:format( " ~n Scheduler id: ~p
|
|
~n Num scheduler: ~p
|
|
~n Process count: ~p
|
|
~n Process limit: ~p
|
|
~n Memory used by erlang processes: ~p
|
|
~n Memory allocated by erlang processes: ~p
|
|
~n The total amount of memory allocated: ~p
|
|
~n",
|
|
Res),
|
|
ok;
|
|
action(backup, Node, _Args, _Opts) ->
|
|
case call(Node, {app_misc, backup, []}) of
|
|
{error, Msg} ->
|
|
io:format("~s~n", [Msg]);
|
|
{ok, FileName} ->
|
|
io:format("backup file:~s~n", [FileName]),
|
|
io:format("backup file to remote ......~n", []),
|
|
Result = os:cmd("bash copy_to_remote.sh " ++ FileName),
|
|
io:format("~s~n", [Result])
|
|
end,
|
|
ok;
|
|
|
|
action(pause_accept, Node, _Args, _Opts) ->
|
|
io:format("Pause accept new client ~p~n", [Node]),
|
|
call(Node, {app_misc, pause_accept, []}),
|
|
ok;
|
|
action(resume_accept, Node, _Args, _Opts) ->
|
|
io:format("Resume accept new client ~p~n", [Node]),
|
|
call(Node, {app_misc, resume_accept, []}),
|
|
ok;
|
|
action(accept_state, Node, _Args, _Opts) ->
|
|
Res = call(Node, {app_misc, can_accept_new, []}),
|
|
io:format("Node ~p accept state:~p~n ", [Node, Res]),
|
|
ok;
|
|
action(reload, Node, _Args, _Opts) ->
|
|
io:format("Reloading node ~p~n", [Node]),
|
|
call(Node, {main, reload, []});
|
|
action(stop_all, MasterNode, _Args, _Opts) ->
|
|
io:format("Stopping and halting all node~n", []),
|
|
PidMRefs = [{spawn_monitor(fun() ->
|
|
call(Node, {main, stop_and_halt, [5]})
|
|
end), Node}
|
|
|| Node <- nodes() -- [MasterNode]],
|
|
[receive
|
|
{'DOWN', MRef, process, _, normal} ->
|
|
ok;
|
|
{'DOWN', MRef, process, _, Reason} ->
|
|
io:format("Node ~p Error, Reason ~p", [Node, Reason])
|
|
end || {{_Pid, MRef}, Node} <- PidMRefs],
|
|
call(MasterNode, {main, stop_and_halt, [5]}),
|
|
ok;
|
|
action(stop, Node, _Args, _Opts) ->
|
|
io:format("Stopping and halting node ~p~n", [Node]),
|
|
call(Node, {main, stop_and_halt, [5]});
|
|
action(Command, _Node, Args, Opts) ->
|
|
io:format("Command: ~p Args: ~p Opts: ~p~n", [Command, Args, Opts]),
|
|
invalid_command.
|
|
|
|
call(Node, {Mod, Fun, Args}) ->
|
|
%%rpc_call(Node, Mod, Fun, lists:map(fun list_to_binary/1, Args)).
|
|
rpc_call(Node, Mod, Fun, Args).
|
|
|
|
rpc_call(Node, Mod, Fun, Args) ->
|
|
rpc:call(Node, Mod, Fun, Args, ?RPC_TIMEOUT).
|
|
|
|
|
|
quit(Status) ->
|
|
case os:type() of
|
|
{unix, _} ->
|
|
halt(Status);
|
|
{win32, _} ->
|
|
init:stop(Status),
|
|
receive
|
|
after infinity ->
|
|
ok
|
|
end
|
|
end.
|