refactor(mix): undo the `bin/emqx` script split into helper files

This commit is contained in:
Thales Macedo Garitezi 2021-12-30 12:02:36 -03:00
parent 54a6674715
commit c70a47bba6
No known key found for this signature in database
GPG Key ID: DD279F8152A9B6DD
7 changed files with 361 additions and 399 deletions

View File

@ -1,62 +0,0 @@
#!/usr/bin/env bash
DEBUG="${DEBUG:-0}"
if [ "$DEBUG" -eq 1 ]; then
set -x
fi
ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/.. || exit 1; pwd -P)"
# shellcheck disable=SC1090,SC1091
. "$ROOT_DIR"/releases/emqx_vars
# defined in emqx_vars
export RUNNER_ROOT_DIR
export RUNNER_ETC_DIR
export REL_VSN
export RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
export CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
export REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
export SCHEMA_MOD=emqx_conf_schema
WHOAMI=$(whoami)
export WHOAMI
# Make sure data/configs exists
export CONFIGS_DIR="$RUNNER_DATA_DIR/configs"
# hocon try to read environment variables starting with "EMQX_"
export HOCON_ENV_OVERRIDE_PREFIX='EMQX_'
export ROOTDIR="$RUNNER_ROOT_DIR"
export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export ERTS_LIB_DIR="$ERTS_DIR/../lib"
export DYNLIBS_DIR="$RUNNER_ROOT_DIR/dynlibs"
## backward compatible
if [ -d "$ERTS_DIR/lib" ]; then
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
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)
if [ "$ULIMIT_F" -lt 1024 ]; then
echo "!!!!"
echo "!!!! WARNING: ulimit -n is ${ULIMIT_F}; 1024 is the recommended minimum."
echo "!!!!"
fi
SED_REPLACE="sed -i "
case $(sed --help 2>&1) in
*GNU*) SED_REPLACE="sed -i ";;
*BusyBox*) SED_REPLACE="sed -i ";;
*) SED_REPLACE=(sed -i '' );;
esac
export SED_REPLACE

View File

@ -1,69 +0,0 @@
#!/usr/bin/env bash
## NOTE: those are defined separately from `common_defs.sh` because
## they require `common_functions.sh` to be sourced prior to sourcing
## this file. Basically, the definitions below depend on the function
## `call_hocon`, which is defined in `common_functions.sh`. Also,
## they require the variable `IS_BOOT_COMMAND` to be set to either
## `yes` or `no` for the name definition to be done properly.
## This should be sourced after the calling script has define the
## `$COMMAND` variable.
## make EMQX_NODE_COOKIE right
if [ -n "${EMQX_NODE_NAME:-}" ]; then
export EMQX_NODE__NAME="${EMQX_NODE_NAME}"
unset EMQX_NODE_NAME
fi
## Possible ways to configure emqx node name:
## 1. configure node.name in emqx.conf
## 2. override with environment variable EMQX_NODE__NAME
## Node name is either short-name (without '@'), e.g. 'emqx'
## or long name (with '@') e.g. 'emqx@example.net' or 'emqx@127.0.0.1'
NAME="${EMQX_NODE__NAME:-}"
if [ -z "$NAME" ]; then
if [ "$IS_BOOT_COMMAND" = 'yes' ]; 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
vm_args_file="$(latest_vm_args 'EMQX_NODE__NAME')"
NAME="$(grep -E '^-s?name' "${vm_args_file}" | awk '{print $2}')"
fi
fi
# force to use 'emqx' short name
[ -z "$NAME" ] && NAME='emqx'
export MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia/$NAME"
case "$NAME" in
*@*)
NAME_TYPE='-name'
;;
*)
NAME_TYPE='-sname'
esac
export NAME_TYPE
SHORT_NAME="$(echo "$NAME" | awk -F'@' '{print $1}')"
export ESCRIPT_NAME="$SHORT_NAME"
PIPE_DIR="${PIPE_DIR:-/$RUNNER_DATA_DIR/${WHOAMI}_erl_pipes/$NAME/}"
## make EMQX_NODE_COOKIE right
if [ -n "${EMQX_NODE_COOKIE:-}" ]; then
export EMQX_NODE__COOKIE="${EMQX_NODE_COOKIE}"
unset EMQX_NODE_COOKIE
fi
COOKIE="${EMQX_NODE__COOKIE:-}"
if [ -z "$COOKIE" ]; then
if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
COOKIE="$(call_hocon -s "$SCHEMA_MOD" -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.cookie | tr -d \")"
else
vm_args_file="$(latest_vm_args 'EMQX_NODE__COOKIE')"
COOKIE="$(grep -E '^-setcookie' "${vm_args_file}" | awk '{print $2}')"
fi
fi
if [ -z "$COOKIE" ]; then
die "Please set node.cookie in $RUNNER_ETC_DIR/emqx.conf or override from environment variable EMQX_NODE__COOKIE"
fi

View File

@ -1,246 +0,0 @@
#!/usr/bin/env bash
# Echo to stderr on errors
echoerr() { echo "ERROR: $*" 1>&2; }
die() {
echoerr "ERROR: $1"
errno=${2:-1}
exit "$errno"
}
assert_node_alive() {
if ! relx_nodetool "ping" > /dev/null; then
die "node_is_not_running!" 1
fi
}
check_erlang_start() {
"$BINDIR/$PROGNAME" \
-noshell \
-boot_var RELEASE_LIB "$ERTS_LIB_DIR/lib" \
-boot "$REL_DIR/start_clean" \
-s crypto start \
-s erlang halt
}
# Simple way to check the correct user and fail early
check_user() {
# Validate that the user running the script is the owner of the
# RUN_DIR.
if [ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]; then
if [ "x$WHOAMI" != "xroot" ]; then
echo "You need to be root or use sudo to run this command"
exit 1
fi
CMD="DEBUG=$DEBUG \"$RUNNER_SCRIPT\" "
for ARG in "$@"; do
CMD="${CMD} \"$ARG\""
done
# This will drop priviledges into the runner user
# It exec's in a new shell and the current shell will exit
exec su - "$RUNNER_USER" -c "$CMD"
fi
}
# Get node pid
relx_get_pid() {
if output="$(relx_nodetool rpcterms os getpid)"
then
# shellcheck disable=SC2001 # Escaped quote taken as closing quote in editor
echo "$output" | sed -e 's/"//g'
return 0
else
echo "$output"
return 1
fi
}
# Connect to a remote node
relx_rem_sh() {
# Generate a unique id used to allow multiple remsh to the same node
# transparently
id="remsh$(relx_gen_id)-${NAME}"
# Get the node's ticktime so that we use the same thing.
TICKTIME="$(relx_nodetool rpcterms net_kernel get_net_ticktime)"
# shellcheck disable=SC2086 # $EPMD_ARG is supposed to be split by whitespace
# shellcheck disable=SC2153 # $NAME_TYPE is defined by `common_defs2.sh`, which runs before this is called
# Setup remote shell command to control node
if [ "$IS_ELIXIR" = "yes" ]
then
exec "$REL_DIR/iex" \
--remsh "$NAME" \
--boot-var RELEASE_LIB "$ERTS_LIB_DIR" \
--cookie "$COOKIE" \
--hidden \
--erl "-kernel net_ticktime $TICKTIME" \
--erl "$EPMD_ARG" \
--erl "$NAME_TYPE $id" \
--boot "$REL_DIR/start_clean"
else
exec "$BINDIR/erl" "$NAME_TYPE" "$id" \
-remsh "$NAME" -boot "$REL_DIR/start_clean" \
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
-setcookie "$COOKIE" -hidden -kernel net_ticktime "$TICKTIME" \
$EPMD_ARG
fi
}
# Generate a random id
relx_gen_id() {
od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}
# Control a node
relx_nodetool() {
command="$1"; shift
ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
-setcookie "$COOKIE" "$command" "$@"
}
call_hocon() {
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" hocon "$@" \
|| die "call_hocon_failed: $*" $?
}
# Run an escript in the node's environment
relx_escript() {
shift; scriptpath="$1"; shift
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
}
# Output a start command for the last argument of run_erl.
# The calling script defines `$START_OPTION`, when the command is to
# start EMQX in the background.
relx_start_command() {
printf "exec \"%s\" \"%s\"" "$RUNNER_SCRIPT" \
"$START_OPTION"
}
# Function to generate app.config and vm.args
generate_config() {
local name_type="$1"
local node_name="$2"
## Delete the *.siz files first or it cann't start after
## changing the config 'log.rotation.size'
rm -rf "${RUNNER_LOG_DIR}"/*.siz
EMQX_LICENSE_CONF_OPTION=""
if [ "${EMQX_LICENSE_CONF:-}" != "" ]; then
EMQX_LICENSE_CONF_OPTION="-c ${EMQX_LICENSE_CONF}"
fi
## timestamp for each generation
local NOW_TIME
NOW_TIME="$(call_hocon now_time)"
## ths command populates two files: app.<time>.config and vm.<time>.args
## NOTE: the generate command merges environment variables to the base config (emqx.conf),
## but does not include the cluster-override.conf and local-override.conf
## meaning, certain overrides will not be mapped to app.<time>.config file
## disable SC2086 to allow EMQX_LICENSE_CONF_OPTION to split
# shellcheck disable=SC2086
call_hocon -v -t "$NOW_TIME" -I "$CONFIGS_DIR/" -s $SCHEMA_MOD -c "$RUNNER_ETC_DIR"/emqx.conf $EMQX_LICENSE_CONF_OPTION -d "$RUNNER_DATA_DIR"/configs generate
## filenames are per-hocon convention
local CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
local HOCON_GEN_ARG_FILE="$CONFIGS_DIR/vm.$NOW_TIME.args"
# This is needed by the Elixir scripts.
# Do NOT append `.config`.
RELEASE_SYS_CONFIG="$CONFIGS_DIR/app.$NOW_TIME"
export RELEASE_SYS_CONFIG
CONFIG_ARGS="-config $CONF_FILE -args_file $HOCON_GEN_ARG_FILE"
## Merge hocon generated *.args into the vm.args
TMP_ARG_FILE="$CONFIGS_DIR/vm.args.tmp"
cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
echo "" >> "$TMP_ARG_FILE"
echo "-pa ${REL_DIR}/consolidated" >> "$TMP_ARG_FILE"
## read lines from generated vm.<time>.args file
## drop comment lines, and empty lines using sed
## pipe the lines to a while loop
sed '/^#/d' "$HOCON_GEN_ARG_FILE" | sed '/^$/d' | while IFS='' read -r ARG_LINE || [ -n "$ARG_LINE" ]; do
## in the loop, split the 'key[:space:]value' pair
ARG_KEY=$(echo "$ARG_LINE" | awk '{$NF="";print}')
ARG_VALUE=$(echo "$ARG_LINE" | awk '{print $NF}')
## use the key to look up in vm.args file for the value
TMP_ARG_VALUE=$(grep "^$ARG_KEY" "$TMP_ARG_FILE" || true | awk '{print $NF}')
## compare generated (to override) value to original (to be overriden) value
if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
## if they are different
if [ -n "$TMP_ARG_VALUE" ]; then
## if the old value is present, replace it with generated value
sh -c "$SED_REPLACE 's|^$ARG_KEY.*$|$ARG_LINE|' $TMP_ARG_FILE"
else
## otherwise append generated value to the end
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
fi
fi
done
echo "$name_type $node_name" >> "$TMP_ARG_FILE"
## rename the generated vm.<time>.args file
mv -f "$TMP_ARG_FILE" "$HOCON_GEN_ARG_FILE"
# shellcheck disable=SC2086
if ! relx_nodetool chkconfig $CONFIG_ARGS; then
die "failed_to_check_config $CONFIG_ARGS"
fi
}
# check if a PID is down
is_down() {
PID="$1"
if ps -p "$PID" >/dev/null; then
# still around
# shellcheck disable=SC2009 # this grep pattern is not a part of the progra names
if ps -p "$PID" | grep -q 'defunct'; then
# zombie state, print parent pid
parent="$(ps -o ppid= -p "$PID" | tr -d ' ')"
echo "WARN: $PID is marked <defunct>, parent:"
ps -p "$parent"
return 0
fi
return 1
fi
# it's gone
return 0
}
wait_for() {
local WAIT_TIME
local CMD
WAIT_TIME="$1"
shift
CMD="$*"
while true; do
if $CMD >/dev/null 2>&1; then
return 0
fi
if [ "$WAIT_TIME" -le 0 ]; then
return 1
fi
WAIT_TIME=$((WAIT_TIME - 1))
sleep 1
done
}
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
echoerr "node not initialized?"
# shellcheck disable=SC2153 # $COMMAND is defined by the calling script
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
}

374
bin/emqx
View File

@ -4,11 +4,26 @@
set -euo pipefail set -euo pipefail
BASE="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)" DEBUG="${DEBUG:-0}"
# shellcheck disable=SC1090,SC1091 if [ "$DEBUG" -eq 1 ]; then
source "$BASE/bin/common_defs.sh" set -x
# shellcheck disable=SC1090,SC1091 fi
source "$BASE/bin/common_functions.sh"
ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)"
# shellcheck disable=SC1090
. "$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"
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
SCHEMA_MOD=emqx_conf_schema
WHOAMI=$(whoami)
# Make sure log directory exists # Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR" mkdir -p "$RUNNER_LOG_DIR"
@ -17,8 +32,49 @@ mkdir -p "$RUNNER_LOG_DIR"
mkdir -p "$RUNNER_DATA_DIR" mkdir -p "$RUNNER_DATA_DIR"
# Make sure data/configs exists # Make sure data/configs exists
CONFIGS_DIR="$RUNNER_DATA_DIR/configs"
mkdir -p "$CONFIGS_DIR" mkdir -p "$CONFIGS_DIR"
# hocon try to read environment variables starting with "EMQX_"
export HOCON_ENV_OVERRIDE_PREFIX='EMQX_'
export ROOTDIR="$RUNNER_ROOT_DIR"
export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
export BINDIR="$ERTS_DIR/bin"
export EMU="beam"
export PROGNAME="erl"
export ERTS_LIB_DIR="$ERTS_DIR/../lib"
DYNLIBS_DIR="$RUNNER_ROOT_DIR/dynlibs"
# Echo to stderr on errors
echoerr() { echo "ERROR: $*" 1>&2; }
die() {
echoerr "ERROR: $1"
errno=${2:-1}
exit "$errno"
}
assert_node_alive() {
if ! relx_nodetool "ping" > /dev/null; then
die "node_is_not_running!" 1
fi
}
# Echo to stderr on errors
echoerr() { echo "$*" 1>&2; }
check_erlang_start() {
# RELEASE_LIB is used by Elixir
"$BINDIR/$PROGNAME" \
-noshell \
-boot_var RELEASE_LIB "$ERTS_LIB_DIR/lib" \
-boot "$REL_DIR/start_clean" \
-s crypto start \
-s erlang halt
}
usage() { usage() {
local command="$1" local command="$1"
@ -69,14 +125,14 @@ usage() {
echo "Print path to Erlang runtime dir" echo "Print path to Erlang runtime dir"
;; ;;
rpc) rpc)
echo "Usage $REL_NAME rpc MODULE FUNCTION [ARGS, ...]" echo "Usge $REL_NAME rpc MODULE FUNCTION [ARGS, ...]"
echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC" echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC"
echo "The result of the RPC call must be 'ok'" echo "The result of the RPC call must be 'ok'"
echo "This command blocks for at most 60 seconds in case the node" echo "This command blocks for at most 60 seconds in case the node"
echo "does not reply the call in time" echo "does not reply the call in time"
;; ;;
rpcterms) rpcterms)
echo "Usage $REL_NAME rpcterms MODULE FUNCTION [ARGS, ...]" echo "Usge $REL_NAME rpcterms MODULE FUNCTION [ARGS, ...]"
echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC" 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" echo "The result of the RPC call is pretty-printed as an Erlang term"
;; ;;
@ -166,6 +222,30 @@ if ! check_erlang_start >/dev/null 2>&1; then
echoerr "WARNING: There seem to be missing dynamic libs from the OS. Using libs from ${DYNLIBS_DIR}" echoerr "WARNING: There seem to be missing dynamic libs from the OS. Using libs from ${DYNLIBS_DIR}"
fi fi
## backward compatible
if [ -d "$ERTS_DIR/lib" ]; then
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
fi
# Simple way to check the correct user and fail early
check_user() {
# Validate that the user running the script is the owner of the
# RUN_DIR.
if [ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]; then
if [ "x$WHOAMI" != "xroot" ]; then
echo "You need to be root or use sudo to run this command"
exit 1
fi
CMD="DEBUG=$DEBUG \"$RUNNER_SCRIPT\" "
for ARG in "$@"; do
CMD="${CMD} \"$ARG\""
done
# This will drop priviledges into the runner user
# It exec's in a new shell and the current shell will exit
exec su - "$RUNNER_USER" -c "$CMD"
fi
}
# Make sure the user running this script is the owner and/or su to that user # Make sure the user running this script is the owner and/or su to that user
check_user "$@" check_user "$@"
ES=$? ES=$?
@ -173,9 +253,224 @@ if [ "$ES" -ne 0 ]; then
exit $ES exit $ES
fi fi
## IS_BOOT_COMMAND is set to be later used by `common_defs2.sh` to # EPMD_ARG="-start_epmd true $PROTO_DIST_ARG"
## inspect node name and cookie from hocon config (or env variable), NO_EPMD="-start_epmd false -epmd_module ekka_epmd -proto_dist ekka"
## which also resides in `common_defs2.sh`. EPMD_ARG="${EPMD_ARG:-${NO_EPMD}}"
# Warn the user if ulimit -n is less than 1024
ULIMIT_F=$(ulimit -n)
if [ "$ULIMIT_F" -lt 1024 ]; then
echo "!!!!"
echo "!!!! WARNING: ulimit -n is ${ULIMIT_F}; 1024 is the recommended minimum."
echo "!!!!"
fi
SED_REPLACE="sed -i "
case $(sed --help 2>&1) in
*GNU*) SED_REPLACE="sed -i ";;
*BusyBox*) SED_REPLACE="sed -i ";;
*) SED_REPLACE="sed -i '' ";;
esac
# Get node pid
relx_get_pid() {
if output="$(relx_nodetool rpcterms os getpid)"
then
# shellcheck disable=SC2001 # Escaped quote taken as closing quote in editor
echo "$output" | sed -e 's/"//g'
return 0
else
echo "$output"
return 1
fi
}
# Connect to a remote node
relx_rem_sh() {
# Generate a unique id used to allow multiple remsh to the same node
# transparently
id="remsh$(relx_gen_id)-${NAME}"
# Get the node's ticktime so that we use the same thing.
TICKTIME="$(relx_nodetool rpcterms net_kernel get_net_ticktime)"
# shellcheck disable=SC2086 # $EPMD_ARG is supposed to be split by whitespace
# Setup remote shell command to control node
if [ "$IS_ELIXIR" = "yes" ]
then
exec "$REL_DIR/iex" \
--remsh "$NAME" \
--boot-var RELEASE_LIB "$ERTS_LIB_DIR" \
--cookie "$COOKIE" \
--hidden \
--erl "-kernel net_ticktime $TICKTIME" \
--erl "$EPMD_ARG" \
--erl "$NAME_TYPE $id" \
--boot "$REL_DIR/start_clean"
else
exec "$BINDIR/erl" "$NAME_TYPE" "$id" \
-remsh "$NAME" -boot "$REL_DIR/start_clean" \
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
-setcookie "$COOKIE" -hidden -kernel net_ticktime "$TICKTIME" \
$EPMD_ARG
fi
}
# Generate a random id
relx_gen_id() {
od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
}
# Control a node
relx_nodetool() {
command="$1"; shift
ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
-setcookie "$COOKIE" "$command" "$@"
}
call_hocon() {
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" hocon "$@" \
|| die "call_hocon_failed: $*" $?
}
# Run an escript in the node's environment
relx_escript() {
shift; scriptpath="$1"; shift
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
}
# Output a start command for the last argument of run_erl
relx_start_command() {
printf "exec \"%s\" \"%s\"" "$RUNNER_SCRIPT" \
"$START_OPTION"
}
# Function to generate app.config and vm.args
generate_config() {
local name_type="$1"
local node_name="$2"
## Delete the *.siz files first or it cann't start after
## changing the config 'log.rotation.size'
rm -rf "${RUNNER_LOG_DIR}"/*.siz
EMQX_LICENSE_CONF_OPTION=""
if [ "${EMQX_LICENSE_CONF:-}" != "" ]; then
EMQX_LICENSE_CONF_OPTION="-c ${EMQX_LICENSE_CONF}"
fi
## timestamp for each generation
local NOW_TIME
NOW_TIME="$(call_hocon now_time)"
## ths command populates two files: app.<time>.config and vm.<time>.args
## NOTE: the generate command merges environment variables to the base config (emqx.conf),
## but does not include the cluster-override.conf and local-override.conf
## meaning, certain overrides will not be mapped to app.<time>.config file
## disable SC2086 to allow EMQX_LICENSE_CONF_OPTION to split
# shellcheck disable=SC2086
call_hocon -v -t "$NOW_TIME" -I "$CONFIGS_DIR/" -s $SCHEMA_MOD -c "$RUNNER_ETC_DIR"/emqx.conf $EMQX_LICENSE_CONF_OPTION -d "$RUNNER_DATA_DIR"/configs generate
## filenames are per-hocon convention
local CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
local HOCON_GEN_ARG_FILE="$CONFIGS_DIR/vm.$NOW_TIME.args"
# This is needed by the Elixir scripts.
# Do NOT append `.config`.
RELEASE_SYS_CONFIG="$CONFIGS_DIR/app.$NOW_TIME"
export RELEASE_SYS_CONFIG
CONFIG_ARGS="-config $CONF_FILE -args_file $HOCON_GEN_ARG_FILE"
## Merge hocon generated *.args into the vm.args
TMP_ARG_FILE="$CONFIGS_DIR/vm.args.tmp"
cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
echo "" >> "$TMP_ARG_FILE"
echo "-pa ${REL_DIR}/consolidated" >> "$TMP_ARG_FILE"
## read lines from generated vm.<time>.args file
## drop comment lines, and empty lines using sed
## pipe the lines to a while loop
sed '/^#/d' "$HOCON_GEN_ARG_FILE" | sed '/^$/d' | while IFS='' read -r ARG_LINE || [ -n "$ARG_LINE" ]; do
## in the loop, split the 'key[:space:]value' pair
ARG_KEY=$(echo "$ARG_LINE" | awk '{$NF="";print}')
ARG_VALUE=$(echo "$ARG_LINE" | awk '{print $NF}')
## use the key to look up in vm.args file for the value
TMP_ARG_VALUE=$(grep "^$ARG_KEY" "$TMP_ARG_FILE" || true | awk '{print $NF}')
## compare generated (to override) value to original (to be overriden) value
if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
## if they are different
if [ -n "$TMP_ARG_VALUE" ]; then
## if the old value is present, replace it with generated value
sh -c "$SED_REPLACE 's|^$ARG_KEY.*$|$ARG_LINE|' $TMP_ARG_FILE"
else
## otherwise append generated value to the end
echo "$ARG_LINE" >> "$TMP_ARG_FILE"
fi
fi
done
echo "$name_type $node_name" >> "$TMP_ARG_FILE"
## rename the generated vm.<time>.args file
mv -f "$TMP_ARG_FILE" "$HOCON_GEN_ARG_FILE"
# shellcheck disable=SC2086
if ! relx_nodetool chkconfig $CONFIG_ARGS; then
die "failed_to_check_config $CONFIG_ARGS"
fi
}
# check if a PID is down
is_down() {
PID="$1"
if ps -p "$PID" >/dev/null; then
# still around
# shellcheck disable=SC2009 # this grep pattern is not a part of the progra names
if ps -p "$PID" | grep -q 'defunct'; then
# zombie state, print parent pid
parent="$(ps -o ppid= -p "$PID" | tr -d ' ')"
echo "WARN: $PID is marked <defunct>, parent:"
ps -p "$parent"
return 0
fi
return 1
fi
# it's gone
return 0
}
wait_for() {
local WAIT_TIME
local CMD
WAIT_TIME="$1"
shift
CMD="$*"
while true; do
if $CMD >/dev/null 2>&1; then
return 0
fi
if [ "$WAIT_TIME" -le 0 ]; then
return 1
fi
WAIT_TIME=$((WAIT_TIME - 1))
sleep 1
done
}
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
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
}
## IS_BOOT_COMMAND is set for later to inspect node name and cookie from hocon config (or env variable)
case "${COMMAND}" in case "${COMMAND}" in
start|console|console_clean|foreground) start|console|console_clean|foreground)
IS_BOOT_COMMAND='yes' IS_BOOT_COMMAND='yes'
@ -184,10 +479,62 @@ case "${COMMAND}" in
IS_BOOT_COMMAND='no' IS_BOOT_COMMAND='no'
;; ;;
esac esac
export IS_BOOT_COMMAND
# shellcheck disable=SC1090,SC1091 ## make EMQX_NODE_COOKIE right
source "$BASE/bin/common_defs2.sh" if [ -n "${EMQX_NODE_NAME:-}" ]; then
export EMQX_NODE__NAME="${EMQX_NODE_NAME}"
unset EMQX_NODE_NAME
fi
## Possible ways to configure emqx node name:
## 1. configure node.name in emqx.conf
## 2. override with environment variable EMQX_NODE__NAME
## Node name is either short-name (without '@'), e.g. 'emqx'
## or long name (with '@') e.g. 'emqx@example.net' or 'emqx@127.0.0.1'
NAME="${EMQX_NODE__NAME:-}"
if [ -z "$NAME" ]; then
if [ "$IS_BOOT_COMMAND" = 'yes' ]; 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
vm_args_file="$(latest_vm_args 'EMQX_NODE__NAME')"
NAME="$(grep -E '^-s?name' "${vm_args_file}" | awk '{print $2}')"
fi
fi
# force to use 'emqx' short name
[ -z "$NAME" ] && NAME='emqx'
MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia/$NAME"
case "$NAME" in
*@*)
NAME_TYPE='-name'
;;
*)
NAME_TYPE='-sname'
esac
SHORT_NAME="$(echo "$NAME" | awk -F'@' '{print $1}')"
export ESCRIPT_NAME="$SHORT_NAME"
PIPE_DIR="${PIPE_DIR:-/$RUNNER_DATA_DIR/${WHOAMI}_erl_pipes/$NAME/}"
## make EMQX_NODE_COOKIE right
if [ -n "${EMQX_NODE_COOKIE:-}" ]; then
export EMQX_NODE__COOKIE="${EMQX_NODE_COOKIE}"
unset EMQX_NODE_COOKIE
fi
COOKIE="${EMQX_NODE__COOKIE:-}"
if [ -z "$COOKIE" ]; then
if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
COOKIE="$(call_hocon -s $SCHEMA_MOD -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.cookie | tr -d \")"
else
vm_args_file="$(latest_vm_args 'EMQX_NODE__COOKIE')"
COOKIE="$(grep -E '^-setcookie' "${vm_args_file}" | awk '{print $2}')"
fi
fi
if [ -z "$COOKIE" ]; then
die "Please set node.cookie in $RUNNER_ETC_DIR/emqx.conf or override from environment variable EMQX_NODE__COOKIE"
fi
cd "$ROOTDIR" cd "$ROOTDIR"
@ -209,7 +556,6 @@ case "${COMMAND}" in
HEART_OPTION="start" HEART_OPTION="start"
;; ;;
esac esac
export START_OPTION
RUN_PARAM="$*" RUN_PARAM="$*"
# Set arguments for the heart command # Set arguments for the heart command

View File

@ -305,7 +305,6 @@ permafy(TargetNode, RelName, Vsn) ->
?INFO("Made release permanent: ~p", [Vsn]), ?INFO("Made release permanent: ~p", [Vsn]),
%% upgrade/downgrade the scripts by replacing them %% upgrade/downgrade the scripts by replacing them
Scripts = [RelNameStr, RelNameStr ++ "_ctl", Scripts = [RelNameStr, RelNameStr ++ "_ctl",
"common_defs.sh", "common_defs2.sh", "common_functions.sh",
"nodetool", "install_upgrade.escript"], "nodetool", "install_upgrade.escript"],
[{ok, _} = file:copy(filename:join(["bin", File++"-"++Vsn]), [{ok, _} = file:copy(filename:join(["bin", File++"-"++Vsn]),
filename:join(["bin", File])) filename:join(["bin", File]))

View File

@ -312,10 +312,7 @@ defmodule EMQXUmbrella.MixProject do
for name <- [ for name <- [
"emqx", "emqx",
"emqx_ctl", "emqx_ctl"
"common_defs.sh",
"common_defs2.sh",
"common_functions.sh"
] do ] do
Mix.Generator.copy_file( Mix.Generator.copy_file(
"bin/#{name}", "bin/#{name}",

View File

@ -328,9 +328,6 @@ relx_overlay(ReleaseType, Edition) ->
, {template, "data/emqx_vars", "releases/emqx_vars"} , {template, "data/emqx_vars", "releases/emqx_vars"}
, {template, "data/BUILT_ON", "releases/{{release_version}}/BUILT_ON"} , {template, "data/BUILT_ON", "releases/{{release_version}}/BUILT_ON"}
, {copy, "bin/emqx", "bin/emqx"} , {copy, "bin/emqx", "bin/emqx"}
, {copy, "bin/common_defs.sh", "bin/common_defs.sh"}
, {copy, "bin/common_defs2.sh", "bin/common_defs2.sh"}
, {copy, "bin/common_functions.sh", "bin/common_functions.sh"}
, {copy, "bin/emqx_ctl", "bin/emqx_ctl"} , {copy, "bin/emqx_ctl", "bin/emqx_ctl"}
, {copy, "bin/node_dump", "bin/node_dump"} , {copy, "bin/node_dump", "bin/node_dump"}
, {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript"} , {copy, "bin/install_upgrade.escript", "bin/install_upgrade.escript"}