mirror of
https://github.com/processone/ejabberd
synced 2025-10-03 09:49:18 +02:00
New ejabberdctl option CTL_OVER_HTTP
This uses an HTTP connection to execute the command, which is way faster than starting an erlang node
This commit is contained in:
parent
ab8a39e71f
commit
46a64c0f68
3 changed files with 96 additions and 16 deletions
|
@ -198,6 +198,17 @@
|
|||
#
|
||||
#CONTRIB_MODULES_CONF_DIR=/etc/ejabberd/modules
|
||||
|
||||
#.
|
||||
#' CTL_OVER_HTTP: Path to ejabberdctl HTTP listener socket
|
||||
#
|
||||
# To speedup ejabberdctl execution time for ejabberd commands,
|
||||
# you can setup an ejabberd_http listener with ejabberd_ctl handling requests,
|
||||
# listening in a unix domain socket.
|
||||
#
|
||||
# Default: disabled
|
||||
#
|
||||
#CTL_OVER_HTTP=sockets/ctl_over_http.sock
|
||||
|
||||
#.
|
||||
#'
|
||||
# vim: foldmarker=#',#. foldmethod=marker:
|
||||
|
|
|
@ -334,6 +334,47 @@ wait_status()
|
|||
[ $timeout -gt 0 ]
|
||||
}
|
||||
|
||||
exec_other_command()
|
||||
{
|
||||
if [ -z "$CTL_OVER_HTTP" ] || [ ! -S "$CTL_OVER_HTTP" ] \
|
||||
|| [ ! -x "$(command -v curl)" ] || [ -z "$1" ] || [ "$1" = "help" ] \
|
||||
|| [ "$1" = "mnesia_info_ctl" ]|| [ "$1" = "print_sql_schema" ] ; then
|
||||
exec_erl "$(uid ctl)" -hidden -noinput \
|
||||
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
|
||||
-s ejabberd_ctl \
|
||||
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
|
||||
result=$?
|
||||
case $result in
|
||||
3) help;;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
else
|
||||
exec_ctl_over_http_socket "$@"
|
||||
fi
|
||||
}
|
||||
|
||||
exec_ctl_over_http_socket()
|
||||
{
|
||||
CARGS='{"ctl-command-line": "'${*}'"}'
|
||||
TEMPHEADERS=temp-headers.log
|
||||
curl \
|
||||
--unix-socket ${CTL_OVER_HTTP} \
|
||||
--header "Content-Type: application/json" \
|
||||
--header "Accept: application/json" \
|
||||
--data "${CARGS}" \
|
||||
--dump-header ${TEMPHEADERS} \
|
||||
--no-progress-meter \
|
||||
"http://localhost/ctl/${1}"
|
||||
result=$(sed -n 's/.*status-code: \([0-9]*\).*/\1/p' < $TEMPHEADERS)
|
||||
rm ${TEMPHEADERS}
|
||||
case $result in
|
||||
2|3) exec_other_command help ${1};;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
}
|
||||
|
||||
# ensure we can change current directory to SPOOL_DIR
|
||||
[ -d "$SPOOL_DIR" ] || exec_cmd mkdir -p "$SPOOL_DIR"
|
||||
cd "$SPOOL_DIR" || {
|
||||
|
@ -402,15 +443,6 @@ case $1 in
|
|||
;;
|
||||
*)
|
||||
set_dist_client
|
||||
exec_erl "$(uid ctl)" -hidden -noinput \
|
||||
-eval 'net_kernel:connect_node('"'$ERLANG_NODE'"')' \
|
||||
-s ejabberd_ctl \
|
||||
-extra "$ERLANG_NODE" $NO_TIMEOUT "$@"
|
||||
result=$?
|
||||
case $result in
|
||||
2|3) help;;
|
||||
*) :;;
|
||||
esac
|
||||
exit $result
|
||||
exec_other_command "$@"
|
||||
;;
|
||||
esac
|
||||
|
|
|
@ -28,7 +28,7 @@
|
|||
-behaviour(gen_server).
|
||||
-author('alexey@process-one.net').
|
||||
|
||||
-export([start/0, start_link/0, process/1, process2/2]).
|
||||
-export([start/0, start_link/0, process/1, process/2, process2/2]).
|
||||
%% gen_server callbacks
|
||||
-export([init/1, handle_call/3, handle_cast/2, handle_info/2,
|
||||
terminate/2, code_change/3]).
|
||||
|
@ -37,6 +37,7 @@
|
|||
|
||||
-include("ejabberd_ctl.hrl").
|
||||
-include("ejabberd_commands.hrl").
|
||||
-include("ejabberd_http.hrl").
|
||||
-include("logger.hrl").
|
||||
-include("ejabberd_stacktrace.hrl").
|
||||
|
||||
|
@ -115,15 +116,51 @@ code_change(_OldVsn, State, _Extra) ->
|
|||
{ok, State}.
|
||||
|
||||
%%-----------------------------
|
||||
%% Process
|
||||
%% Process http
|
||||
%%-----------------------------
|
||||
|
||||
-spec process_http([binary()], tuple()) -> {non_neg_integer(), [{binary(), binary()}], string()}.
|
||||
|
||||
process_http([Call], #request{data = Data} = Request) when is_binary(Call) and is_record(Request, request) ->
|
||||
[{<<"ctl-command-line">>, LineBin}] = extract_args(Data),
|
||||
LineStrings = string:split(binary_to_list(LineBin), " ", all),
|
||||
process_http2(LineStrings, ?DEFAULT_VERSION).
|
||||
|
||||
process_http2(["--version", Arg | Args], _) ->
|
||||
Version =
|
||||
try
|
||||
list_to_integer(Arg)
|
||||
catch _:_ ->
|
||||
throw({invalid_version, Arg})
|
||||
end,
|
||||
process_http2(Args, Version);
|
||||
|
||||
process_http2(Args, Version) ->
|
||||
{String, Code} = process2(Args, [], Version),
|
||||
String2 = case String of
|
||||
[] -> String;
|
||||
_ -> [String, "\n"]
|
||||
end,
|
||||
{200, [{<<"status-code">>, integer_to_binary(Code)}], String2}.
|
||||
|
||||
%% Be tolerant to make API more easily usable from command-line pipe.
|
||||
extract_args(<<"\n">>) -> [];
|
||||
extract_args(Data) ->
|
||||
Maps = misc:json_decode(Data),
|
||||
maps:to_list(Maps).
|
||||
|
||||
%%-----------------------------
|
||||
%% Process command line
|
||||
%%-----------------------------
|
||||
|
||||
-spec process([string()]) -> non_neg_integer().
|
||||
process(Args) ->
|
||||
process(Args, ?DEFAULT_VERSION).
|
||||
|
||||
-spec process([string() | binary()], non_neg_integer() | tuple()) -> non_neg_integer().
|
||||
|
||||
-spec process([string()], non_neg_integer()) -> non_neg_integer().
|
||||
process([Call], Request) when is_binary(Call) and is_record(Request, request) ->
|
||||
process_http([Call], Request);
|
||||
|
||||
%% The commands status, stop and restart are defined here to ensure
|
||||
%% they are usable even if ejabberd is completely stopped.
|
||||
|
@ -232,7 +269,7 @@ process2(Args, AccessCommands, Auth, Version) ->
|
|||
io:format(lists:flatten(["\n" | String]++["\n"])),
|
||||
[CommandString | _] = Args,
|
||||
process(["help" | [CommandString]], Version),
|
||||
{lists:flatten(String), ?STATUS_ERROR};
|
||||
{lists:flatten(String), ?STATUS_USAGE};
|
||||
{String, Code}
|
||||
when is_list(String) and is_integer(Code) ->
|
||||
{lists:flatten(String), Code};
|
||||
|
@ -271,7 +308,7 @@ try_run_ctp(Args, Auth, AccessCommands, Version) ->
|
|||
try_call_command(Args, Auth, AccessCommands, Version);
|
||||
false ->
|
||||
print_usage(Version),
|
||||
{"", ?STATUS_USAGE};
|
||||
{"", ?STATUS_BADRPC};
|
||||
Status ->
|
||||
{"", Status}
|
||||
catch
|
||||
|
@ -288,7 +325,7 @@ try_run_ctp(Args, Auth, AccessCommands, Version) ->
|
|||
try_call_command(Args, Auth, AccessCommands, Version) ->
|
||||
try call_command(Args, Auth, AccessCommands, Version) of
|
||||
{Reason, wrong_command_arguments} ->
|
||||
{Reason, ?STATUS_ERROR};
|
||||
{Reason, ?STATUS_USAGE};
|
||||
Res ->
|
||||
Res
|
||||
catch
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue