feat(./dev): use command style and added 'ctl' command

This commit is contained in:
Zaiming (Stone) Shi 2023-05-03 23:22:16 +02:00
parent 66112fceed
commit c4da84f0be
1 changed files with 114 additions and 29 deletions

139
dev
View File

@ -7,6 +7,14 @@ UNAME="$(uname -s)"
PROJ_ROOT="$(git rev-parse --show-toplevel)" PROJ_ROOT="$(git rev-parse --show-toplevel)"
cd "$PROJ_ROOT" cd "$PROJ_ROOT"
logerr() {
if [ "${TERM:-dumb}" = dumb ]; then
echo -e "ERROR: $*" 1>&2
else
echo -e "$(tput setaf 1)ERROR: $*$(tput sgr0)" 1>&2
fi
}
usage() { usage() {
cat <<EOF cat <<EOF
@ -14,16 +22,24 @@ Run EMQX without building a release (which takes longer time).
Node state is stored in '_build/dev-run/$PROFILE'. Node state is stored in '_build/dev-run/$PROFILE'.
The node is started in interactive mode without a boot file. The node is started in interactive mode without a boot file.
USAGE: $0 [OPTION] USAGE: $0 [COMMAND] [OPTION[]
COMMANDS:
help: Print this usage info.
run: Default command.
remsh: Attach to running node's remote console.
Target node name is to be specified with -n|--name,
otherwise defaults to 'emqx@127.0.0.1'.
ctl: Equivalent to 'emqx ctl'.
ctl command arguments should be passed after '--'
e.g. $0 ctl -- help
OPTIONS: OPTIONS:
-h|--help: Print this help usage info.
-p|--profile: emqx | emqx-enterprise, defaults to 'PROFILE' env. -p|--profile: emqx | emqx-enterprise, defaults to 'PROFILE' env.
-c|--compile: Force recompile, otherwise starts with the already built libs -c|--compile: Force recompile, otherwise starts with the already built libs
in '_build/\$PROFILE/lib/'. in '_build/\$PROFILE/lib/'.
-e|--ekka-epmd: Force to use ekka_epmd. -e|--ekka-epmd: Force to use ekka_epmd.
-n|--name: Node name, defaults to \$EMQX_NODE_NAME env. -n|--name: Node name, defaults to \$EMQX_NODE_NAME env.
-r|--remsh [NAME]: Attach to running node's remote console.
ENVIRONMENT VARIABLES: ENVIRONMENT VARIABLES:
@ -45,24 +61,35 @@ PROFILE="${PROFILE:-emqx}"
FORCE_COMPILE=0 FORCE_COMPILE=0
# Do not start using ekka epmd by default, so your IDE can connect to it # Do not start using ekka epmd by default, so your IDE can connect to it
EKKA_EPMD=0 EKKA_EPMD=0
REMSH=0 COMMAND='run'
while [ "$#" -gt 0 ]; do case "${1:-novalue}" in
case $1 in novalue)
-h|--help) ;;
run)
shift
;;
remsh)
COMMAND='remsh'
shift
;;
ctl)
COMMAND='ctl'
shift
;;
help)
usage usage
exit 0 exit 0
;; ;;
-*)
;;
esac
while [ "$#" -gt 0 ]; do
case $1 in
-n|--name) -n|--name)
EMQX_NODE_NAME="$2" EMQX_NODE_NAME="$2"
shift 1 shift 1
;; ;;
-r|--remsh)
REMSH=1
if [[ $2 == *@* ]]; then
EMQX_NODE_NAME="$2"
shift 1
fi
;;
-p|--profile) -p|--profile)
PROFILE="${2}" PROFILE="${2}"
shift 1; shift 1;
@ -73,8 +100,13 @@ while [ "$#" -gt 0 ]; do
-e|--ekka-epmd) -e|--ekka-epmd)
EKKA_EPMD=1 EKKA_EPMD=1
;; ;;
--)
shift
PASSTHROUGH_ARGS=("$@")
break
;;
*) *)
echo "Unknown argument $1" >&2 logerr "Unknown argument $1"
exit 1 exit 1
;; ;;
esac esac
@ -159,7 +191,8 @@ render_hocon_conf() {
mustache platform_etc_dir "${EMQX_ETC_DIR}" "$output" mustache platform_etc_dir "${EMQX_ETC_DIR}" "$output"
} }
call_hocon() { ## Make comma separated quoted strings
make_erlang_args() {
local in=("$@") local in=("$@")
local args='' local args=''
for arg in "${in[@]}"; do for arg in "${in[@]}"; do
@ -169,7 +202,14 @@ call_hocon() {
args="$args, \"$arg\"" args="$args, \"$arg\""
fi fi
done done
erl -noshell -eval "{ok, _} = application:ensure_all_started(hocon), ok = hocon_cli:main([$args]), init:stop()." echo "$args"
}
call_hocon() {
args="$(make_erlang_args "$@")"
erl -noshell \
-eval "{ok, _} = application:ensure_all_started(hocon), \
ok = hocon_cli:main([$args]), init:stop()."
} }
# Function to generate app.config and vm.args # Function to generate app.config and vm.args
@ -226,6 +266,13 @@ is_current_profile_app() {
return 1 return 1
fi fi
;; ;;
*emqx_telemetry*)
if [ "$PROFILE" = 'emqx-enterprise' ]; then
return 1
else
return 0
fi
;;
*) *)
if [ "$PROFILE" = 'emqx' ]; then if [ "$PROFILE" = 'emqx' ]; then
if [ -f "$app"/BSL.txt ]; then if [ -f "$app"/BSL.txt ]; then
@ -274,7 +321,7 @@ boot() {
Apps=[${APPS}], Apps=[${APPS}],
ok=lists:foreach(fun application:load/1, Apps), ok=lists:foreach(fun application:load/1, Apps),
io:format(user, \"~nLoaded ~p apps~n\", [length(Apps)]), io:format(user, \"~nLoaded ~p apps~n\", [length(Apps)]),
application:ensure_all_started(emqx_machine). {ok, _} = application:ensure_all_started(emqx_machine).
" "
# shellcheck disable=SC2086 # shellcheck disable=SC2086
@ -288,22 +335,60 @@ boot() {
} }
# Generate a random id # Generate a random id
gen_node_id() { gen_tmp_node_name() {
od -t u -N 4 /dev/urandom | head -n1 | awk '{print $2 % 1000}' local rnd
rnd="$(od -t u -N 4 /dev/urandom | head -n1 | awk '{print $2 % 1000}')"
echo "remsh${rnd}-$EMQX_NODE_NAME}"
} }
remsh() { remsh() {
id="remsh$(gen_node_id)-${EMQX_NODE_NAME}" local tmpnode
tmpnode="$(gen_tmp_node_name)"
# shellcheck disable=SC2086 # shellcheck disable=SC2086
erl -name "$id" \ erl -name "$tmpnode" \
-setcookie "$COOKIE" \
-hidden \ -hidden \
-setcookie "$COOKIE" \
-remsh "$EMQX_NODE_NAME" \ -remsh "$EMQX_NODE_NAME" \
$EPMD_ARGS $EPMD_ARGS
} }
if [ $REMSH -eq 0 ]; then ctl() {
boot if [ -z "${PASSTHROUGH_ARGS:-}" ]; then
else logerr "Need at least one argument for ctl command"
remsh logerr "e.g. $0 ctl -- help"
exit 1
fi fi
local tmpnode args rpc_code output result
tmpnode="$(gen_tmp_node_name)"
args="$(make_erlang_args "${PASSTHROUGH_ARGS[@]}")"
rpc_code="
case rpc:call('$EMQX_NODE_NAME', emqx_ctl, run_command, [[$args]]) of
ok ->
init:stop(0);
Error ->
io:format(\"~p~n\", [Error]),
init:stop(1)
end"
set +e
# shellcheck disable=SC2086
output="$(erl -name "$tmpnode" -setcookie "$COOKIE" -hidden -noshell $EPMD_ARGS -eval "$rpc_code" 2>&1)"
result=$?
if [ $result -eq 0 ]; then
echo -e "$output"
else
logerr "$output"
fi
exit $result
}
case "$COMMAND" in
run)
boot
;;
remsh)
remsh
;;
ctl)
ctl
;;
esac