emqx 24 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771
  1. #!/bin/bash
  2. # -*- tab-width:4;indent-tabs-mode:nil -*-
  3. # ex: ts=4 sw=4 et
  4. set -euo pipefail
  5. DEBUG="${DEBUG:-0}"
  6. if [ "$DEBUG" -eq 1 ]; then
  7. set -x
  8. fi
  9. ROOT_DIR="$(cd "$(dirname "$(readlink "$0" || echo "$0")")"/..; pwd -P)"
  10. # shellcheck disable=SC1090
  11. . "$ROOT_DIR"/releases/emqx_vars
  12. # defined in emqx_vars
  13. export RUNNER_ROOT_DIR
  14. export RUNNER_ETC_DIR
  15. export REL_VSN
  16. RUNNER_SCRIPT="$RUNNER_BIN_DIR/$REL_NAME"
  17. CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
  18. REL_DIR="$RUNNER_ROOT_DIR/releases/$REL_VSN"
  19. SCHEMA_MOD=emqx_conf_schema
  20. WHOAMI=$(whoami)
  21. # Make sure log directory exists
  22. mkdir -p "$RUNNER_LOG_DIR"
  23. # Make sure data directory exists
  24. mkdir -p "$RUNNER_DATA_DIR"
  25. # Make sure data/configs exists
  26. CONFIGS_DIR="$RUNNER_DATA_DIR/configs"
  27. mkdir -p "$CONFIGS_DIR"
  28. # hocon try to read environment variables starting with "EMQX_"
  29. export HOCON_ENV_OVERRIDE_PREFIX='EMQX_'
  30. export ROOTDIR="$RUNNER_ROOT_DIR"
  31. export ERTS_DIR="$ROOTDIR/erts-$ERTS_VSN"
  32. export BINDIR="$ERTS_DIR/bin"
  33. export EMU="beam"
  34. export PROGNAME="erl"
  35. export ERTS_LIB_DIR="$ERTS_DIR/../lib"
  36. DYNLIBS_DIR="$RUNNER_ROOT_DIR/dynlibs"
  37. # Echo to stderr on errors
  38. echoerr() { echo "ERROR: $*" 1>&2; }
  39. die() {
  40. echoerr "ERROR: $1"
  41. errno=${2:-1}
  42. exit "$errno"
  43. }
  44. assert_node_alive() {
  45. if ! relx_nodetool "ping" > /dev/null; then
  46. die "node_is_not_running!" 1
  47. fi
  48. }
  49. # Echo to stderr on errors
  50. echoerr() { echo "$*" 1>&2; }
  51. check_erlang_start() {
  52. "$BINDIR/$PROGNAME" -noshell -boot "$REL_DIR/start_clean" -s crypto start -s erlang halt
  53. }
  54. usage() {
  55. local command="$1"
  56. case "$command" in
  57. start)
  58. echo "Start EMQ X service in daemon mode"
  59. ;;
  60. stop)
  61. echo "Stop the running EMQ X program"
  62. ;;
  63. restart|reboot)
  64. echo "Restart $EMQX_DESCRIPTION"
  65. ;;
  66. pid)
  67. echo "Print out $EMQX_DESCRIPTION process identifier"
  68. ;;
  69. ping)
  70. echo "Check if the $EMQX_DESCRIPTION node is up and running"
  71. echo "This command exit with 0 silently if node is running"
  72. ;;
  73. escript)
  74. echo "Execute a escript using the Erlang runtime from EMQ X package installation"
  75. echo "For example $REL_NAME escript /path/to/my/escript my_arg1 my_arg2"
  76. ;;
  77. attach)
  78. echo "This command is applicable when $EMQX_DESCRIPTION is started in daemon"
  79. echo "mode. it attaches the current shell to EMQ X's control console"
  80. echo "through a named pipe"
  81. echo "WARNING: try to use the safer alternative, remote_console command."
  82. ;;
  83. remote_console)
  84. echo "Start a dummy Erlang node and hidden-connect $EMQX_DESCRIPTION to"
  85. echo "with an interactive Erlang shell"
  86. ;;
  87. console)
  88. echo "Boot up $EMQX_DESCRIPTION service in an interactive Erlang shell"
  89. echo "This command is useful for troubleshooting"
  90. ;;
  91. console_clean)
  92. echo "This command does NOT boot up the $EMQX_DESCRIPTION service"
  93. echo "It only starts an interactive Erlang console with all the"
  94. echo "EMQ X code available"
  95. ;;
  96. foreground)
  97. echo "Start $EMQX_DESCRIPTION in foreground mode"
  98. ;;
  99. ertspath)
  100. echo "Print path to Erlang runtime dir"
  101. ;;
  102. rpc)
  103. echo "Usge $REL_NAME rpc MODULE FUNCTION [ARGS, ...]"
  104. echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC"
  105. echo "The result of the RPC call must be 'ok'"
  106. echo "This command blocks for at most 60 seconds in case the node"
  107. echo "does not reply the call in time"
  108. ;;
  109. rpcterms)
  110. echo "Usge $REL_NAME rpcterms MODULE FUNCTION [ARGS, ...]"
  111. echo "Connect to the $EMQX_DESCRIPTION node and make an Erlang RPC"
  112. echo "The result of the RPC call is pretty-printed as an Erlang term"
  113. ;;
  114. root_dir)
  115. echo "Print EMQ X installation root dir"
  116. ;;
  117. eval)
  118. echo "Evaluate an Erlang expression in the EMQ X node"
  119. ;;
  120. versions)
  121. echo "List installed EMQ X versions and their status"
  122. ;;
  123. unpack)
  124. echo "Usage: $REL_NAME unpack [VERSION]"
  125. echo "Unpacks a release package VERSION, it assumes that this"
  126. echo "release package tarball has already been deployed at one"
  127. echo "of the following locations:"
  128. echo " releases/<relname>-<version>.tar.gz"
  129. echo " releases/<relname>-<version>.zip"
  130. ;;
  131. install)
  132. echo "Usage: $REL_NAME install [VERSION]"
  133. echo "Installs a release package VERSION, it assumes that this"
  134. echo "release package tarball has already been deployed at one"
  135. echo "of the following locations:"
  136. echo " releases/<relname>-<version>.tar.gz"
  137. echo " releases/<relname>-<version>.zip"
  138. echo ""
  139. echo " --no-permanent Install release package VERSION but"
  140. echo " don't make it permanent"
  141. ;;
  142. uninstall)
  143. echo "Usage: $REL_NAME uninstall [VERSION]"
  144. echo "Uninstalls a release VERSION, it will only accept"
  145. echo "versions that are not currently in use"
  146. ;;
  147. upgrade)
  148. echo "Usage: $REL_NAME upgrade [VERSION]"
  149. echo "Upgrades the currently running release to VERSION, it assumes"
  150. echo "that a release package tarball has already been deployed at one"
  151. echo "of the following locations:"
  152. echo " releases/<relname>-<version>.tar.gz"
  153. echo " releases/<relname>-<version>.zip"
  154. echo ""
  155. echo " --no-permanent Install release package VERSION but"
  156. echo " don't make it permanent"
  157. ;;
  158. downgrade)
  159. echo "Usage: $REL_NAME downgrade [VERSION]"
  160. echo "Downgrades the currently running release to VERSION, it assumes"
  161. echo "that a release package tarball has already been deployed at one"
  162. echo "of the following locations:"
  163. echo " releases/<relname>-<version>.tar.gz"
  164. echo " releases/<relname>-<version>.zip"
  165. echo ""
  166. echo " --no-permanent Install release package VERSION but"
  167. echo " don't make it permanent"
  168. ;;
  169. *)
  170. 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} <help>"
  171. ;;
  172. esac
  173. }
  174. COMMAND="${1:-}"
  175. if [ "${2:-}" = 'help' ]; then
  176. ## 'ctl' command has its own usage info
  177. if [ "$COMMAND" != 'ctl' ]; then
  178. usage "$COMMAND"
  179. exit 0
  180. fi
  181. fi
  182. if ! check_erlang_start >/dev/null 2>&1; then
  183. BUILT_ON="$(head -1 "${REL_DIR}/BUILT_ON")"
  184. ## failed to start, might be due to missing libs, try to be portable
  185. export LD_LIBRARY_PATH="$DYNLIBS_DIR:$LD_LIBRARY_PATH"
  186. if ! check_erlang_start; then
  187. ## it's hopeless
  188. echoerr "FATAL: Unable to start Erlang."
  189. echoerr "Please make sure openssl-1.1.1 (libcrypto) and libncurses are installed."
  190. echoerr "Also ensure it's running on the correct platform,"
  191. echoerr "this EMQ X release is built for $BUILT_ON"
  192. exit 1
  193. fi
  194. echoerr "WARNING: There seem to be missing dynamic libs from the OS. Using libs from ${DYNLIBS_DIR}"
  195. fi
  196. ## backward compatible
  197. if [ -d "$ERTS_DIR/lib" ]; then
  198. export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
  199. fi
  200. # Simple way to check the correct user and fail early
  201. check_user() {
  202. # Validate that the user running the script is the owner of the
  203. # RUN_DIR.
  204. if [ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]; then
  205. if [ "x$WHOAMI" != "xroot" ]; then
  206. echo "You need to be root or use sudo to run this command"
  207. exit 1
  208. fi
  209. CMD="DEBUG=$DEBUG \"$RUNNER_SCRIPT\" "
  210. for ARG in "$@"; do
  211. CMD="${CMD} \"$ARG\""
  212. done
  213. # This will drop priviledges into the runner user
  214. # It exec's in a new shell and the current shell will exit
  215. exec su - "$RUNNER_USER" -c "$CMD"
  216. fi
  217. }
  218. # Make sure the user running this script is the owner and/or su to that user
  219. check_user "$@"
  220. ES=$?
  221. if [ "$ES" -ne 0 ]; then
  222. exit $ES
  223. fi
  224. # EPMD_ARG="-start_epmd true $PROTO_DIST_ARG"
  225. NO_EPMD="-start_epmd false -epmd_module ekka_epmd -proto_dist ekka"
  226. EPMD_ARG="${EPMD_ARG:-${NO_EPMD}}"
  227. # Warn the user if ulimit -n is less than 1024
  228. ULIMIT_F=$(ulimit -n)
  229. if [ "$ULIMIT_F" -lt 1024 ]; then
  230. echo "!!!!"
  231. echo "!!!! WARNING: ulimit -n is ${ULIMIT_F}; 1024 is the recommended minimum."
  232. echo "!!!!"
  233. fi
  234. SED_REPLACE="sed -i "
  235. case $(sed --help 2>&1) in
  236. *GNU*) SED_REPLACE="sed -i ";;
  237. *BusyBox*) SED_REPLACE="sed -i ";;
  238. *) SED_REPLACE="sed -i '' ";;
  239. esac
  240. # Get node pid
  241. relx_get_pid() {
  242. if output="$(relx_nodetool rpcterms os getpid)"
  243. then
  244. # shellcheck disable=SC2001 # Escaped quote taken as closing quote in editor
  245. echo "$output" | sed -e 's/"//g'
  246. return 0
  247. else
  248. echo "$output"
  249. return 1
  250. fi
  251. }
  252. # Connect to a remote node
  253. relx_rem_sh() {
  254. # Generate a unique id used to allow multiple remsh to the same node
  255. # transparently
  256. id="remsh$(relx_gen_id)-${NAME}"
  257. # Get the node's ticktime so that we use the same thing.
  258. TICKTIME="$(relx_nodetool rpcterms net_kernel get_net_ticktime)"
  259. # shellcheck disable=SC2086 # $EPMD_ARG is supposed to be split by whitespace
  260. # Setup remote shell command to control node
  261. exec "$BINDIR/erl" "$NAME_TYPE" "$id" -remsh "$NAME" -boot "$REL_DIR/start_clean" \
  262. -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
  263. -setcookie "$COOKIE" -hidden -kernel net_ticktime "$TICKTIME" $EPMD_ARG
  264. }
  265. # Generate a random id
  266. relx_gen_id() {
  267. od -t x -N 4 /dev/urandom | head -n1 | awk '{print $2}'
  268. }
  269. # Control a node
  270. relx_nodetool() {
  271. command="$1"; shift
  272. ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \
  273. "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
  274. -setcookie "$COOKIE" "$command" "$@"
  275. }
  276. call_hocon() {
  277. "$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" hocon "$@" \
  278. || die "call_hocon_failed: $*" $?
  279. }
  280. # Run an escript in the node's environment
  281. relx_escript() {
  282. shift; scriptpath="$1"; shift
  283. "$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" "$@"
  284. }
  285. # Output a start command for the last argument of run_erl
  286. relx_start_command() {
  287. printf "exec \"%s\" \"%s\"" "$RUNNER_SCRIPT" \
  288. "$START_OPTION"
  289. }
  290. # Function to generate app.config and vm.args
  291. generate_config() {
  292. local name_type="$1"
  293. local node_name="$2"
  294. ## Delete the *.siz files first or it cann't start after
  295. ## changing the config 'log.rotation.size'
  296. rm -rf "${RUNNER_LOG_DIR}"/*.siz
  297. EMQX_LICENSE_CONF_OPTION=""
  298. if [ "${EMQX_LICENSE_CONF:-}" != "" ]; then
  299. EMQX_LICENSE_CONF_OPTION="-c ${EMQX_LICENSE_CONF}"
  300. fi
  301. ## timestamp for each generation
  302. local NOW_TIME
  303. NOW_TIME="$(call_hocon now_time)"
  304. ## ths command populates two files: app.<time>.config and vm.<time>.args
  305. ## disable SC2086 to allow EMQX_LICENSE_CONF_OPTION to split
  306. # shellcheck disable=SC2086
  307. 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
  308. ## filenames are per-hocon convention
  309. local CONF_FILE="$CONFIGS_DIR/app.$NOW_TIME.config"
  310. local HOCON_GEN_ARG_FILE="$CONFIGS_DIR/vm.$NOW_TIME.args"
  311. CONFIG_ARGS="-config $CONF_FILE -args_file $HOCON_GEN_ARG_FILE"
  312. ## Merge hocon generated *.args into the vm.args
  313. TMP_ARG_FILE="$CONFIGS_DIR/vm.args.tmp"
  314. cp "$RUNNER_ETC_DIR/vm.args" "$TMP_ARG_FILE"
  315. echo "" >> "$TMP_ARG_FILE"
  316. echo "-pa ${REL_DIR}/consolidated" >> "$TMP_ARG_FILE"
  317. ## read lines from generated vm.<time>.args file
  318. ## drop comment lines, and empty lines using sed
  319. ## pipe the lines to a while loop
  320. sed '/^#/d' "$HOCON_GEN_ARG_FILE" | sed '/^$/d' | while IFS='' read -r ARG_LINE || [ -n "$ARG_LINE" ]; do
  321. ## in the loop, split the 'key[:space:]value' pair
  322. ARG_KEY=$(echo "$ARG_LINE" | awk '{$NF="";print}')
  323. ARG_VALUE=$(echo "$ARG_LINE" | awk '{print $NF}')
  324. ## use the key to look up in vm.args file for the value
  325. TMP_ARG_VALUE=$(grep "^$ARG_KEY" "$TMP_ARG_FILE" || true | awk '{print $NF}')
  326. ## compare generated (to override) value to original (to be overriden) value
  327. if [ "$ARG_VALUE" != "$TMP_ARG_VALUE" ] ; then
  328. ## if they are different
  329. if [ -n "$TMP_ARG_VALUE" ]; then
  330. ## if the old value is present, replace it with generated value
  331. sh -c "$SED_REPLACE 's|^$ARG_KEY.*$|$ARG_LINE|' $TMP_ARG_FILE"
  332. else
  333. ## otherwise append generated value to the end
  334. echo "$ARG_LINE" >> "$TMP_ARG_FILE"
  335. fi
  336. fi
  337. done
  338. echo "$name_type $node_name" >> "$TMP_ARG_FILE"
  339. ## rename the generated vm.<time>.args file
  340. mv -f "$TMP_ARG_FILE" "$HOCON_GEN_ARG_FILE"
  341. # shellcheck disable=SC2086
  342. if ! relx_nodetool chkconfig $CONFIG_ARGS; then
  343. die "failed_to_check_config $CONFIG_ARGS"
  344. fi
  345. }
  346. # check if a PID is down
  347. is_down() {
  348. PID="$1"
  349. if ps -p "$PID" >/dev/null; then
  350. # still around
  351. # shellcheck disable=SC2009 # this grep pattern is not a part of the progra names
  352. if ps -p "$PID" | grep -q 'defunct'; then
  353. # zombie state, print parent pid
  354. parent="$(ps -o ppid= -p "$PID" | tr -d ' ')"
  355. echo "WARN: $PID is marked <defunct>, parent:"
  356. ps -p "$parent"
  357. return 0
  358. fi
  359. return 1
  360. fi
  361. # it's gone
  362. return 0
  363. }
  364. wait_for() {
  365. local WAIT_TIME
  366. local CMD
  367. WAIT_TIME="$1"
  368. shift
  369. CMD="$*"
  370. while true; do
  371. if $CMD >/dev/null 2>&1; then
  372. return 0
  373. fi
  374. if [ "$WAIT_TIME" -le 0 ]; then
  375. return 1
  376. fi
  377. WAIT_TIME=$((WAIT_TIME - 1))
  378. sleep 1
  379. done
  380. }
  381. latest_vm_args() {
  382. local hint_var_name="$1"
  383. local vm_args_file
  384. vm_args_file="$(find "$CONFIGS_DIR" -type f -name "vm.*.args" | sort | tail -1)"
  385. if [ -f "$vm_args_file" ]; then
  386. echo "$vm_args_file"
  387. else
  388. echoerr "ERRRO: node not initialized?"
  389. echoerr "Generated config file vm.*.args is not found for command '$COMMAND'"
  390. echoerr "in config dir: $CONFIGS_DIR"
  391. echoerr "In case the file has been deleted while the node is running,"
  392. echoerr "set environment variable '$hint_var_name' to continue"
  393. exit 1
  394. fi
  395. }
  396. ## IS_BOOT_COMMAND is set for later to inspect node name and cookie from hocon config (or env variable)
  397. case "${COMMAND}" in
  398. start|console|console_clean|foreground)
  399. IS_BOOT_COMMAND='yes'
  400. ;;
  401. *)
  402. IS_BOOT_COMMAND='no'
  403. ;;
  404. esac
  405. ## Possible ways to configure emqx node name:
  406. ## 1. configure node.name in emqx.conf
  407. ## 2. override with environment variable EMQX_NODE_NAME
  408. ## Node name is either short-name (without '@'), e.g. 'emqx'
  409. ## or long name (with '@') e.g. 'emqx@example.net' or 'emqx@127.0.0.1'
  410. NAME="${EMQX_NODE_NAME:-}"
  411. if [ -z "$NAME" ]; then
  412. if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
  413. # for boot commands, inspect emqx.conf for node name
  414. NAME="$(call_hocon -s $SCHEMA_MOD -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.name | tr -d \")"
  415. else
  416. vm_args_file="$(latest_vm_args 'EMQX_NODE_NAME')"
  417. NAME="$(grep -E '^-s?name' "${vm_args_file}" | awk '{print $2}')"
  418. fi
  419. fi
  420. # force to use 'emqx' short name
  421. [ -z "$NAME" ] && NAME='emqx'
  422. MNESIA_DATA_DIR="$RUNNER_DATA_DIR/mnesia/$NAME"
  423. case "$NAME" in
  424. *@*)
  425. NAME_TYPE='-name'
  426. ;;
  427. *)
  428. NAME_TYPE='-sname'
  429. esac
  430. SHORT_NAME="$(echo "$NAME" | awk -F'@' '{print $1}')"
  431. export ESCRIPT_NAME="$SHORT_NAME"
  432. PIPE_DIR="${PIPE_DIR:-/$RUNNER_DATA_DIR/${WHOAMI}_erl_pipes/$NAME/}"
  433. COOKIE="${EMQX_NODE_COOKIE:-}"
  434. if [ -z "$COOKIE" ]; then
  435. if [ "$IS_BOOT_COMMAND" = 'yes' ]; then
  436. COOKIE="$(call_hocon -s $SCHEMA_MOD -I "$CONFIGS_DIR/" -c "$RUNNER_ETC_DIR"/emqx.conf get node.cookie | tr -d \")"
  437. else
  438. vm_args_file="$(latest_vm_args 'EMQX_NODE_COOKIE')"
  439. COOKIE="$(grep -E '^-setcookie' "${vm_args_file}" | awk '{print $2}')"
  440. fi
  441. fi
  442. if [ -z "$COOKIE" ]; then
  443. die "Please set node.cookie in $RUNNER_ETC_DIR/emqx.conf or override from environment variable EMQX_NODE_COOKIE"
  444. fi
  445. cd "$ROOTDIR"
  446. case "${COMMAND}" in
  447. start)
  448. # Make sure a node IS not running
  449. if relx_nodetool "ping" >/dev/null 2>&1; then
  450. die "node_is_already_running!"
  451. fi
  452. # this flag passes down to console mode
  453. # so we know it's intended to be run in daemon mode
  454. export _EMQX_START_MODE="$COMMAND"
  455. case "$COMMAND" in
  456. start)
  457. shift
  458. START_OPTION="console"
  459. HEART_OPTION="start"
  460. ;;
  461. esac
  462. RUN_PARAM="$*"
  463. # Set arguments for the heart command
  464. set -- "$RUNNER_SCRIPT" "$HEART_OPTION"
  465. [ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"
  466. # Export the HEART_COMMAND
  467. HEART_COMMAND="$RUNNER_SCRIPT $COMMAND"
  468. export HEART_COMMAND
  469. ## See: http://erlang.org/doc/man/run_erl.html
  470. # Export the RUN_ERL_LOG_GENERATIONS
  471. export RUN_ERL_LOG_GENERATIONS=${RUN_ERL_LOG_GENERATIONS:-"5"}
  472. # Export the RUN_ERL_LOG_MAXSIZE
  473. export RUN_ERL_LOG_MAXSIZE=${RUN_ERL_LOG_MAXSIZE:-"10485760"}
  474. mkdir -p "$PIPE_DIR"
  475. "$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
  476. "$(relx_start_command)"
  477. WAIT_TIME=${WAIT_FOR_ERLANG:-15}
  478. if wait_for "$WAIT_TIME" 'relx_nodetool' 'ping'; then
  479. echo "$EMQX_DESCRIPTION $REL_VSN is started successfully!"
  480. exit 0
  481. else
  482. echo "$EMQX_DESCRIPTION $REL_VSN failed to start within ${WAIT_TIME} seconds,"
  483. echo "see the output of '$0 console' for more information."
  484. echo "If you want to wait longer, set the environment variable"
  485. echo "WAIT_FOR_ERLANG to the number of seconds to wait."
  486. exit 1
  487. fi
  488. ;;
  489. stop)
  490. # Wait for the node to completely stop...
  491. PID="$(relx_get_pid)"
  492. if ! relx_nodetool "stop"; then
  493. echoerr "Graceful shutdown failed PID=[$PID]"
  494. exit 1
  495. fi
  496. WAIT_TIME="${WAIT_FOR_ERLANG_STOP:-60}"
  497. if ! wait_for "$WAIT_TIME" 'is_down' "$PID"; then
  498. msg="dangling after ${WAIT_TIME} seconds"
  499. # also log to syslog
  500. logger -t "${REL_NAME}[${PID}]" "STOP: $msg"
  501. # log to user console
  502. echoerr "stop failed, $msg"
  503. echo "ERROR: $PID is still around"
  504. ps -p "$PID"
  505. exit 1
  506. fi
  507. logger -t "${REL_NAME}[${PID}]" "STOP: OK"
  508. ;;
  509. restart|reboot)
  510. echo "$EMQX_DESCRIPTION $REL_VSN is stopped: $("$RUNNER_BIN_DIR/$REL_NAME" stop)"
  511. "$RUNNER_BIN_DIR/$REL_NAME" start
  512. ;;
  513. pid)
  514. ## Get the VM's pid
  515. if ! relx_get_pid; then
  516. exit 1
  517. fi
  518. ;;
  519. ping)
  520. assert_node_alive
  521. echo pong
  522. ;;
  523. escript)
  524. ## Run an escript under the node's environment
  525. if ! relx_escript "$@"; then
  526. exit 1
  527. fi
  528. ;;
  529. attach)
  530. assert_node_alive
  531. shift
  532. exec "$BINDIR/to_erl" "$PIPE_DIR"
  533. ;;
  534. remote_console)
  535. assert_node_alive
  536. shift
  537. relx_rem_sh
  538. ;;
  539. upgrade|downgrade|install|unpack|uninstall)
  540. if [ -z "${2:-}" ]; then
  541. echo "Missing version argument"
  542. echo "Usage: $REL_NAME $COMMAND {version}"
  543. exit 1
  544. fi
  545. shift
  546. assert_node_alive
  547. ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \
  548. exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
  549. "$COMMAND" "{'$REL_NAME', \"$NAME_TYPE\", '$NAME', '$COOKIE'}" "$@"
  550. ;;
  551. versions)
  552. assert_node_alive
  553. shift
  554. ERL_FLAGS="${ERL_FLAGS:-} $EPMD_ARG" \
  555. exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
  556. "versions" "{'$REL_NAME', \"$NAME_TYPE\", '$NAME', '$COOKIE'}" "$@"
  557. ;;
  558. console|console_clean)
  559. # .boot file typically just $REL_NAME (ie, the app name)
  560. # however, for debugging, sometimes start_clean.boot is useful.
  561. # For e.g. 'setup', one may even want to name another boot script.
  562. case "$COMMAND" in
  563. console)
  564. if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
  565. BOOTFILE="$REL_DIR/$REL_NAME"
  566. else
  567. BOOTFILE="$REL_DIR/start"
  568. fi
  569. ;;
  570. console_clean)
  571. BOOTFILE="$REL_DIR/start_clean"
  572. ;;
  573. esac
  574. # set before generate_config
  575. if [ "${_EMQX_START_MODE:-}" = '' ]; then
  576. export EMQX_LOG__CONSOLE_HANDLER__ENABLE="${EMQX_LOG__CONSOLE_HANDLER__ENABLE:-true}"
  577. fi
  578. #generate app.config and vm.args
  579. generate_config "$NAME_TYPE" "$NAME"
  580. # Setup beam-required vars
  581. EMU="beam"
  582. PROGNAME="${0#*/}"
  583. export EMU
  584. export PROGNAME
  585. # Store passed arguments since they will be erased by `set`
  586. ARGS="$*"
  587. # shellcheck disable=SC2086 # $CONFIG_ARGS $EPMD_ARG are supposed to be split by whitespace
  588. # Build an array of arguments to pass to exec later on
  589. # Build it here because this command will be used for logging.
  590. set -- "$BINDIR/erlexec" \
  591. -boot "$BOOTFILE" -mode "$CODE_LOADING_MODE" \
  592. -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
  593. -mnesia dir "\"${MNESIA_DATA_DIR}\"" \
  594. $CONFIG_ARGS $EPMD_ARG
  595. # Log the startup
  596. logger -t "${REL_NAME}[$$]" "EXEC: $* -- ${1+$ARGS}"
  597. # Start the VM
  598. exec "$@" -- ${1+$ARGS}
  599. ;;
  600. foreground)
  601. # start up the release in the foreground for use by runit
  602. # or other supervision services
  603. # set before generate_config
  604. export EMQX_LOG__CONSOLE_HANDLER__ENABLE="${EMQX_LOG__CONSOLE_HANDLER__ENABLE:-true}"
  605. #generate app.config and vm.args
  606. generate_config "$NAME_TYPE" "$NAME"
  607. [ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
  608. FOREGROUNDOPTIONS="-noshell -noinput +Bd"
  609. # Setup beam-required vars
  610. EMU=beam
  611. PROGNAME="${0#*/}"
  612. export EMU
  613. export PROGNAME
  614. # Store passed arguments since they will be erased by `set`
  615. ARGS="$*"
  616. # shellcheck disable=SC2086 # $CONFIG_ARGS $EPMD_ARG are supposed to be split by whitespace
  617. # Build an array of arguments to pass to exec later on
  618. # Build it here because this command will be used for logging.
  619. set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
  620. -boot "$REL_DIR/$BOOTFILE" -mode "$CODE_LOADING_MODE" \
  621. -boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
  622. -mnesia dir "\"${MNESIA_DATA_DIR}\"" \
  623. $CONFIG_ARGS $EPMD_ARG
  624. # Log the startup
  625. logger -t "${REL_NAME}[$$]" "EXEC: $* -- ${1+$ARGS}"
  626. # Start the VM
  627. exec "$@" -- ${1+$ARGS}
  628. ;;
  629. ertspath)
  630. echo "$ERTS_PATH"
  631. ;;
  632. ctl)
  633. assert_node_alive
  634. shift
  635. relx_nodetool rpc_infinity emqx_ctl run_command "$@"
  636. ;;
  637. rpc)
  638. assert_node_alive
  639. shift
  640. relx_nodetool rpc "$@"
  641. ;;
  642. rpcterms)
  643. assert_node_alive
  644. shift
  645. relx_nodetool rpcterms "$@"
  646. ;;
  647. root_dir)
  648. assert_node_alive
  649. shift
  650. relx_nodetool "eval" 'code:root_dir()'
  651. ;;
  652. eval)
  653. assert_node_alive
  654. shift
  655. relx_nodetool "eval" "$@"
  656. ;;
  657. *)
  658. usage "$COMMAND"
  659. exit 1
  660. ;;
  661. esac
  662. exit 0