summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rwxr-xr-xscripts/rabbitmq-plugins2
-rwxr-xr-xscripts/rabbitmq-plugins.bat10
-rwxr-xr-xscripts/rabbitmqctl5
-rwxr-xr-xscripts/rabbitmqctl.bat12
-rw-r--r--src/rabbit.erl7
-rw-r--r--src/rabbit_cli.erl21
-rw-r--r--src/rabbit_control_main.erl13
-rw-r--r--src/rabbit_epmd_monitor.erl101
-rw-r--r--src/rabbit_nodes.erl20
9 files changed, 150 insertions, 41 deletions
diff --git a/scripts/rabbitmq-plugins b/scripts/rabbitmq-plugins
index 29c4b0c8..22fec32f 100755
--- a/scripts/rabbitmq-plugins
+++ b/scripts/rabbitmq-plugins
@@ -19,11 +19,11 @@
# Non-empty defaults should be set in rabbitmq-env
. `dirname $0`/rabbitmq-env
+RABBITMQ_USE_LONGNAME=${RABBITMQ_USE_LONGNAME} \
exec ${ERL_DIR}erl \
-pa "${RABBITMQ_HOME}/ebin" \
-noinput \
-hidden \
- ${RABBITMQ_NAME_TYPE} rabbitmq-plugins$$ \
-boot "${CLEAN_BOOT_FILE}" \
-s rabbit_plugins_main \
-enabled_plugins_file "$RABBITMQ_ENABLED_PLUGINS_FILE" \
diff --git a/scripts/rabbitmq-plugins.bat b/scripts/rabbitmq-plugins.bat
index 1ed648b0..b27a8586 100755
--- a/scripts/rabbitmq-plugins.bat
+++ b/scripts/rabbitmq-plugins.bat
@@ -23,14 +23,6 @@ set TDP0=%~dp0
set STAR=%*
setlocal enabledelayedexpansion
-if "!RABBITMQ_USE_LONGNAME!"=="" (
- set RABBITMQ_NAME_TYPE="-sname"
-)
-
-if "!RABBITMQ_USE_LONGNAME!"=="true" (
- set RABBITMQ_NAME_TYPE="-name"
-)
-
if "!RABBITMQ_SERVICENAME!"=="" (
set RABBITMQ_SERVICENAME=RabbitMQ
)
@@ -63,7 +55,7 @@ if "!RABBITMQ_PLUGINS_DIR!"=="" (
set RABBITMQ_PLUGINS_DIR=!TDP0!..\plugins
)
-"!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden !RABBITMQ_NAME_TYPE! rabbitmq-plugins!RANDOM!!TIME:~9! -s rabbit_plugins_main -enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" -plugins_dist_dir "!RABBITMQ_PLUGINS_DIR:\=/!" -nodename !RABBITMQ_NODENAME! -extra !STAR!
+"!ERLANG_HOME!\bin\erl.exe" -pa "!TDP0!..\ebin" -noinput -hidden -s rabbit_plugins_main -enabled_plugins_file "!RABBITMQ_ENABLED_PLUGINS_FILE!" -plugins_dist_dir "!RABBITMQ_PLUGINS_DIR:\=/!" -nodename !RABBITMQ_NODENAME! -extra !STAR!
endlocal
endlocal
diff --git a/scripts/rabbitmqctl b/scripts/rabbitmqctl
index d437e251..2237275c 100755
--- a/scripts/rabbitmqctl
+++ b/scripts/rabbitmqctl
@@ -19,11 +19,6 @@
# Non-empty defaults should be set in rabbitmq-env
. `dirname $0`/rabbitmq-env
-# rabbitmqctl starts distribution itself, so we need to make sure epmd
-# is running.
-${ERL_DIR}erl ${RABBITMQ_NAME_TYPE} rabbitmqctl-prelaunch-$$ -noinput \
--eval 'erlang:halt().' -boot "${CLEAN_BOOT_FILE}"
-
# We specify Mnesia dir and sasl error logger since some actions
# (e.g. forget_cluster_node --offline) require us to impersonate the
# real node.
diff --git a/scripts/rabbitmqctl.bat b/scripts/rabbitmqctl.bat
index 6eb2530a..a3734088 100755
--- a/scripts/rabbitmqctl.bat
+++ b/scripts/rabbitmqctl.bat
@@ -27,14 +27,6 @@ if "!RABBITMQ_BASE!"=="" (
set RABBITMQ_BASE=!APPDATA!\RabbitMQ
)
-if "!RABBITMQ_USE_LONGNAME!"=="" (
- set RABBITMQ_NAME_TYPE="-sname"
-)
-
-if "!RABBITMQ_USE_LONGNAME!"=="true" (
- set RABBITMQ_NAME_TYPE="-name"
-)
-
if "!COMPUTERNAME!"=="" (
set COMPUTERNAME=localhost
)
@@ -63,10 +55,6 @@ if not exist "!ERLANG_HOME!\bin\erl.exe" (
exit /B
)
-rem rabbitmqctl starts distribution itself, so we need to make sure epmd
-rem is running.
-"!ERLANG_HOME!\bin\erl.exe" !RABBITMQ_NAME_TYPE! rabbitmqctl-prelaunch-!RANDOM!!TIME:~9! -noinput -eval "erlang:halt()."
-
"!ERLANG_HOME!\bin\erl.exe" ^
-pa "!TDP0!..\ebin" ^
-noinput ^
diff --git a/src/rabbit.erl b/src/rabbit.erl
index 40f24efc..ba78b1ee 100644
--- a/src/rabbit.erl
+++ b/src/rabbit.erl
@@ -118,6 +118,13 @@
{requires, [rabbit_alarm, guid_generator]},
{enables, core_initialized}]}).
+-rabbit_boot_step({rabbit_epmd_monitor,
+ [{description, "epmd monitor"},
+ {mfa, {rabbit_sup, start_restartable_child,
+ [rabbit_epmd_monitor]}},
+ {requires, kernel_ready},
+ {enables, core_initialized}]}).
+
-rabbit_boot_step({core_initialized,
[{description, "core initialized"},
{requires, kernel_ready}]}).
diff --git a/src/rabbit_cli.erl b/src/rabbit_cli.erl
index 47505b3d..cf7b6083 100644
--- a/src/rabbit_cli.erl
+++ b/src/rabbit_cli.erl
@@ -17,7 +17,8 @@
-module(rabbit_cli).
-include("rabbit_cli.hrl").
--export([main/3, parse_arguments/4, rpc_call/4]).
+-export([main/3, start_distribution/0, start_distribution/1,
+ parse_arguments/4, rpc_call/4]).
%%----------------------------------------------------------------------------
@@ -31,6 +32,8 @@
-spec(main/3 :: (fun (([string()], string()) -> parse_result()),
fun ((atom(), atom(), [any()], [any()]) -> any()),
atom()) -> no_return()).
+-spec(start_distribution/0 :: () -> {'ok', pid()} | {'error', any()}).
+-spec(start_distribution/1 :: (string()) -> {'ok', pid()} | {'error', any()}).
-spec(usage/1 :: (atom()) -> no_return()).
-spec(parse_arguments/4 ::
([{atom(), [{string(), optdef()}]} | atom()],
@@ -42,6 +45,8 @@
%%----------------------------------------------------------------------------
main(ParseFun, DoFun, UsageMod) ->
+ error_logger:tty(false),
+ start_distribution(),
{ok, [[NodeStr|_]|_]} = init:get_argument(nodename),
{Command, Opts, Args} =
case ParseFun(init:get_plain_arguments(), NodeStr) of
@@ -101,6 +106,20 @@ main(ParseFun, DoFun, UsageMod) ->
rabbit_misc:quit(2)
end.
+start_distribution() ->
+ start_distribution(list_to_atom(
+ rabbit_misc:format("rabbitmq-cli-~s", [os:getpid()]))).
+
+start_distribution(Name) ->
+ rabbit_nodes:ensure_epmd(),
+ net_kernel:start([Name, name_type()]).
+
+name_type() ->
+ case os:getenv("RABBITMQ_USE_LONGNAME") of
+ "true" -> longnames;
+ _ -> shortnames
+ end.
+
usage(Mod) ->
io:format("~s", [Mod:usage()]),
rabbit_misc:quit(1).
diff --git a/src/rabbit_control_main.erl b/src/rabbit_control_main.erl
index bca740c6..751dbd29 100644
--- a/src/rabbit_control_main.erl
+++ b/src/rabbit_control_main.erl
@@ -124,7 +124,6 @@
%%----------------------------------------------------------------------------
start() ->
- start_distribution(),
rabbit_cli:main(
fun (Args, NodeStr) ->
parse_arguments(Args, NodeStr)
@@ -594,28 +593,18 @@ exit_loop(Port) ->
{Port, _} -> exit_loop(Port)
end.
-start_distribution() ->
- CtlNodeName = rabbit_misc:format("rabbitmqctl-~s", [os:getpid()]),
- {ok, _} = net_kernel:start([list_to_atom(CtlNodeName), name_type()]).
-
become(BecomeNode) ->
error_logger:tty(false),
ok = net_kernel:stop(),
case net_adm:ping(BecomeNode) of
pong -> exit({node_running, BecomeNode});
pang -> io:format(" * Impersonating node: ~s...", [BecomeNode]),
- {ok, _} = net_kernel:start([BecomeNode, name_type()]),
+ {ok, _} = rabbit_cli:start_distribution(BecomeNode),
io:format(" done~n", []),
Dir = mnesia:system_info(directory),
io:format(" * Mnesia directory : ~s~n", [Dir])
end.
-name_type() ->
- case os:getenv("RABBITMQ_USE_LONGNAME") of
- "true" -> longnames;
- _ -> shortnames
- end.
-
%%----------------------------------------------------------------------------
default_if_empty(List, Default) when is_list(List) ->
diff --git a/src/rabbit_epmd_monitor.erl b/src/rabbit_epmd_monitor.erl
new file mode 100644
index 00000000..26155492
--- /dev/null
+++ b/src/rabbit_epmd_monitor.erl
@@ -0,0 +1,101 @@
+%% The contents of this file are subject to the Mozilla Public License
+%% Version 1.1 (the "License"); you may not use this file except in
+%% compliance with the License. You may obtain a copy of the License
+%% at http://www.mozilla.org/MPL/
+%%
+%% Software distributed under the License is distributed on an "AS IS"
+%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
+%% the License for the specific language governing rights and
+%% limitations under the License.
+%%
+%% The Original Code is RabbitMQ.
+%%
+%% The Initial Developer of the Original Code is GoPivotal, Inc.
+%% Copyright (c) 2007-2014 GoPivotal, Inc. All rights reserved.
+%%
+
+-module(rabbit_epmd_monitor).
+
+-behaviour(gen_server).
+
+-export([start_link/0]).
+
+-export([init/1, handle_call/3, handle_cast/2, handle_info/2, terminate/2,
+ code_change/3]).
+
+-record(state, {timer, mod, me, host, port}).
+
+-define(SERVER, ?MODULE).
+-define(CHECK_FREQUENCY, 60000).
+
+%%----------------------------------------------------------------------------
+
+-ifdef(use_specs).
+
+-spec(start_link/0 :: () -> rabbit_types:ok_pid_or_error()).
+
+-endif.
+
+%%----------------------------------------------------------------------------
+%% It's possible for epmd to be killed out from underneath us. If that
+%% happens, then obviously clustering and rabbitmqctl stop
+%% working. This process checks up on epmd and restarts it /
+%% re-registers us with it if it has gone away.
+%%
+%% How could epmd be killed?
+%%
+%% 1) The most popular way for this to happen is when running as a
+%% Windows service. The user starts rabbitmqctl first, and this starts
+%% epmd under the user's account. When they log out epmd is killed.
+%%
+%% 2) Some packagings of (non-RabbitMQ?) Erlang apps might do "killall
+%% epmd" as a shutdown or uninstall step.
+%% ----------------------------------------------------------------------------
+
+start_link() -> gen_server:start_link({local, ?SERVER}, ?MODULE, [], []).
+
+init([]) ->
+ {Me, Host} = rabbit_nodes:parts(node()),
+ Mod = net_kernel:epmd_module(),
+ {port, Port, _Version} = Mod:port_please(Me, Host),
+ {ok, ensure_timer(#state{mod = Mod,
+ me = Me,
+ host = Host,
+ port = Port})}.
+
+handle_call(_Request, _From, State) ->
+ {noreply, State}.
+
+handle_cast(_Msg, State) ->
+ {noreply, State}.
+
+handle_info(check, State) ->
+ check_epmd(State),
+ {noreply, ensure_timer(State#state{timer = undefined})};
+
+handle_info(_Info, State) ->
+ {noreply, State}.
+
+terminate(_Reason, _State) ->
+ ok.
+
+code_change(_OldVsn, State, _Extra) ->
+ {ok, State}.
+
+%%----------------------------------------------------------------------------
+
+ensure_timer(State) ->
+ rabbit_misc:ensure_timer(State, #state.timer, ?CHECK_FREQUENCY, check).
+
+check_epmd(#state{mod = Mod,
+ me = Me,
+ host = Host,
+ port = Port}) ->
+ case Mod:port_please(Me, Host) of
+ noport -> rabbit_log:warning(
+ "epmd does not know us, re-registering ~s at port ~b~n",
+ [Me, Port]),
+ rabbit_nodes:ensure_epmd(),
+ erl_epmd:register_node(Me, Port);
+ _ -> ok
+ end.
diff --git a/src/rabbit_nodes.erl b/src/rabbit_nodes.erl
index 7f7fcc31..d3c0e55f 100644
--- a/src/rabbit_nodes.erl
+++ b/src/rabbit_nodes.erl
@@ -18,7 +18,7 @@
-export([names/1, diagnostics/1, make/1, parts/1, cookie_hash/0,
is_running/2, is_process_running/2,
- cluster_name/0, set_cluster_name/1]).
+ cluster_name/0, set_cluster_name/1, ensure_epmd/0]).
-include_lib("kernel/include/inet.hrl").
@@ -41,6 +41,7 @@
-spec(is_process_running/2 :: (node(), atom()) -> boolean()).
-spec(cluster_name/0 :: () -> binary()).
-spec(set_cluster_name/1 :: (binary()) -> 'ok').
+-spec(ensure_epmd/0 :: () -> 'ok').
-endif.
@@ -197,3 +198,20 @@ cluster_name_default() ->
set_cluster_name(Name) ->
rabbit_runtime_parameters:set_global(cluster_name, Name).
+
+ensure_epmd() ->
+ {ok, Root} = init:get_argument(root),
+ {ok, Prog} = init:get_argument(progname),
+ ID = random:uniform(1000000000),
+ Port = open_port(
+ {spawn_executable, filename:join([Root, "bin", Prog])},
+ [{args, ["-sname", rabbit_misc:format("epmd-starter-~b", [ID]),
+ "-noshell", "-eval", "halt()."]},
+ exit_status, stderr_to_stdout, use_stdio]),
+ port_shutdown_loop(Port).
+
+port_shutdown_loop(Port) ->
+ receive
+ {Port, {exit_status, _Rc}} -> ok;
+ {Port, _} -> port_shutdown_loop(Port)
+ end.