diff --git a/bin/emqx b/bin/emqx index a97e13884..070f4bd7f 100755 --- a/bin/emqx +++ b/bin/emqx @@ -2,8 +2,7 @@ # -*- tab-width:4;indent-tabs-mode:nil -*- # ex: ts=4 sw=4 et -set -e -set -o pipefail +set -euo pipefail DEBUG="${DEBUG:-0}" if [ "$DEBUG" -eq 1 ]; then @@ -66,15 +65,147 @@ assert_node_alive() { # Echo to stderr on errors echoerr() { echo "$*" 1>&2; } -check_eralng_start() { - "$BINDIR/$PROGNAME" -noshell -boot "$REL_DIR/start_clean" -s crypto start -s init stop +check_erlang_start() { + "$BINDIR/$PROGNAME" -noshell -boot "$REL_DIR/start_clean" -s crypto start -s erlang halt } -if ! check_eralng_start >/dev/null 2>&1; then +usage() { + local command="$1" + + case "$command" in + start) + echo "Start EMQ X service in daemon mode" + ;; + stop) + echo "Stop the running EMQ X program" + ;; + restart|reboot) + echo "Restart $EMQX_DESCRIPTION" + ;; + pid) + echo "Print out $EMQX_DESCRIPTION process identifier" + ;; + ping) + echo "Check if the $EMQX_DESCRIPTION node is up and running" + echo "This command exit with 0 silently if node is running" + ;; + escript) + echo "Execute a escript using the Erlang runtime from EMQ X package installation" + echo "For example $REL_NAME escript /path/to/my/escript my_arg1 my_arg2" + ;; + attach) + echo "This command is applicable when $EMQX_DESCRIPTION is started in daemon" + echo "mode. it attaches the current shell to EMQ X's control console" + echo "through a named pipe" + echo "WARNING: try to use the safer alternative, remote_console command." + ;; + remote_console) + echo "Start a dummy Erlang node and hidden-connect $EMQX_DESCRIPTION to" + echo "with an interactive Erlang shell" + ;; + console) + echo "Boot up $EMQX_DESCRIPTION service in an interactive Erlang shell" + echo "This command is useful for troubleshooting" + ;; + console_clean) + echo "This command does NOT boot up the $EMQX_DESCRIPTION service" + echo "It only starts an interactive Erlang console with all the" + echo "EMQ X code available" + ;; + foreground) + echo "Start $EMQX_DESCRIPTION in foreground mode" + ;; + ertspath) + echo "Print path to Erlang runtime dir" + ;; + rpc) + echo "Usge $REL_NAME rpc MODULE FUNCTION [ARGS, ...]" + echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC" + echo "The result of the RPC call must be 'ok'" + echo "This command blocks for at most 60 seconds in case the node" + echo "does not reply the call in time" + ;; + rpcterms) + echo "Usge $REL_NAME rpcterms MODULE FUNCTION [ARGS, ...]" + echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC" + echo "The result of the RPC call is pretty-printed as an Erlang term" + ;; + root_dir) + echo "Print EMQ X installation root dir" + ;; + eval) + echo "Evaluate an Erlang expression in the EMQ X node" + ;; + versions) + echo "List installed EMQ X versions and their status" + ;; + unpack) + echo "Usage: $REL_NAME unpack [VERSION]" + echo "Unpacks a release package VERSION, it assumes that this" + echo "release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/-.tar.gz" + echo " releases/-.zip" + ;; + install) + echo "Usage: $REL_NAME install [VERSION]" + echo "Installs a release package VERSION, it assumes that this" + echo "release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/-.tar.gz" + echo " releases/-.zip" + echo "" + echo " --no-permanent Install release package VERSION but" + echo " don't make it permanent" + ;; + uninstall) + echo "Usage: $REL_NAME uninstall [VERSION]" + echo "Uninstalls a release VERSION, it will only accept" + echo "versions that are not currently in use" + ;; + upgrade) + echo "Usage: $REL_NAME upgrade [VERSION]" + echo "Upgrades the currently running release to VERSION, it assumes" + echo "that a release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/-.tar.gz" + echo " releases/-.zip" + echo "" + echo " --no-permanent Install release package VERSION but" + echo " don't make it permanent" + ;; + downgrade) + echo "Usage: $REL_NAME downgrade [VERSION]" + echo "Downgrades the currently running release to VERSION, it assumes" + echo "that a release package tarball has already been deployed at one" + echo "of the following locations:" + echo " releases/-.tar.gz" + echo " releases/-.zip" + echo "" + echo " --no-permanent Install release package VERSION but" + echo " don't make it permanent" + ;; + *) + echo "Usage: $REL_NAME {start|ertspath|foreground|stop|pid|ping|console|console_clean|attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|ctl|rpc|rpcterms|eval|root_dir} " + ;; + esac +} + +COMMAND="${1:-}" + +if [ "${2:-}" = 'help' ]; then + ## 'ctl' command has its own usage info + if [ "$COMMAND" != 'ctl' ]; then + usage "$COMMAND" + exit 0 + fi +fi + +if ! check_erlang_start >/dev/null 2>&1; then BUILT_ON="$(head -1 "${REL_DIR}/BUILT_ON")" ## failed to start, might be due to missing libs, try to be portable export LD_LIBRARY_PATH="$DYNLIBS_DIR:$LD_LIBRARY_PATH" - if ! check_eralng_start; then + if ! check_erlang_start; then ## it's hopeless echoerr "FATAL: Unable to start Erlang (with libcrypto)." echoerr "Please make sure it's running on the correct platform with all required dependencies." @@ -89,62 +220,6 @@ if [ -d "$ERTS_DIR/lib" ]; then export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH" fi -relx_usage() { - command="$1" - - case "$command" in - unpack) - echo "Usage: $REL_NAME unpack [VERSION]" - echo "Unpacks a release package VERSION, it assumes that this" - echo "release package tarball has already been deployed at one" - echo "of the following locations:" - echo " releases/-.tar.gz" - echo " releases/-.zip" - ;; - install) - echo "Usage: $REL_NAME install [VERSION]" - echo "Installs a release package VERSION, it assumes that this" - echo "release package tarball has already been deployed at one" - echo "of the following locations:" - echo " releases/-.tar.gz" - echo " releases/-.zip" - echo "" - echo " --no-permanent Install release package VERSION but" - echo " don't make it permanent" - ;; - uninstall) - echo "Usage: $REL_NAME uninstall [VERSION]" - echo "Uninstalls a release VERSION, it will only accept" - echo "versions that are not currently in use" - ;; - upgrade) - echo "Usage: $REL_NAME upgrade [VERSION]" - echo "Upgrades the currently running release to VERSION, it assumes" - echo "that a release package tarball has already been deployed at one" - echo "of the following locations:" - echo " releases/-.tar.gz" - echo " releases/-.zip" - echo "" - echo " --no-permanent Install release package VERSION but" - echo " don't make it permanent" - ;; - downgrade) - echo "Usage: $REL_NAME downgrade [VERSION]" - echo "Downgrades the currently running release to VERSION, it assumes" - echo "that a release package tarball has already been deployed at one" - echo "of the following locations:" - echo " releases/-.tar.gz" - echo " releases/-.zip" - echo "" - echo " --no-permanent Install release package VERSION but" - echo " don't make it permanent" - ;; - *) - echo "Usage: $REL_NAME {start|start_boot |ertspath|foreground|stop|pid|ping|console|console_clean|console_boot |attach|remote_console|upgrade|downgrade|install|uninstall|versions|escript|ctl|rpc|rpcterms|eval|root_dir}" - ;; - esac -} - # Simple way to check the correct user and fail early check_user() { # Validate that the user running the script is the owner of the @@ -171,11 +246,9 @@ if [ "$ES" -ne 0 ]; then exit $ES fi -if [ -z "$WITH_EPMD" ]; then - EPMD_ARG="-start_epmd false -epmd_module ekka_epmd -proto_dist ekka" -else - EPMD_ARG="-start_epmd true $PROTO_DIST_ARG" -fi +# EPMD_ARG="-start_epmd true $PROTO_DIST_ARG" +NO_EPMD="-start_epmd false -epmd_module ekka_epmd -proto_dist ekka" +EPMD_ARG="${EPMD_ARG:-${NO_EPMD}}" # Warn the user if ulimit -n is less than 1024 ULIMIT_F=$(ulimit -n) @@ -228,7 +301,7 @@ relx_gen_id() { # Control a node relx_nodetool() { command="$1"; shift - ERL_FLAGS="$ERL_FLAGS $EPMD_ARG" \ + ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \ "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \ -setcookie "$COOKIE" "$command" "$@" } @@ -358,25 +431,29 @@ wait_for() { done } -# Use $CWD/etc/sys.config if exists -if [ -z "$RELX_CONFIG_PATH" ]; then - if [ -f "$RUNNER_ETC_DIR/sys.config" ]; then - RELX_CONFIG_PATH="-config $RUNNER_ETC_DIR/sys.config" +latest_vm_args() { + local hint_var_name="$1" + local vm_args_file + vm_args_file="$(find "$CONFIGS_DIR" -type f -name "vm.*.args" | sort | tail -1)" + if [ -f "$vm_args_file" ]; then + echo "$vm_args_file" else - RELX_CONFIG_PATH="" + echoerr "ERRRO: node not initialized?" + echoerr "Generated config file vm.*.args is not found for command '$COMMAND'" + echoerr "in config dir: $CONFIGS_DIR" + echoerr "In case the file has been deleted while the node is running," + echoerr "set environment variable '$hint_var_name' to continue" + exit 1 fi -fi +} -IS_BOOT_COMMAND='no' -case "$1" in - start|start_boot) +## IS_BOOT_COMMAND is set for later to inspect node name and cookie from hocon config (or env variable) +case "${COMMAND}" in + start|console|console_clean|foreground) IS_BOOT_COMMAND='yes' ;; - console|console_clean|console_boot) - IS_BOOT_COMMAND='yes' - ;; - foreground) - IS_BOOT_COMMAND='yes' + *) + IS_BOOT_COMMAND='no' ;; esac @@ -391,10 +468,8 @@ if [ -z "$NAME" ]; then # for boot commands, inspect emqx.conf for node name NAME="$(call_hocon -s $SCHEMA_MOD -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.name | tr -d \")" else - # for non-boot commands, inspect vm.