relx
This commit is contained in:
parent
3e77773d04
commit
710890dd22
|
@ -7,8 +7,6 @@ deps
|
|||
erl_crash.dump
|
||||
ebin
|
||||
!ebin/.placeholder
|
||||
rel/emqttd
|
||||
rel/emqttd*
|
||||
.concrete/DEV_MODE
|
||||
.rebar
|
||||
test/ebin/*.beam
|
||||
|
@ -28,3 +26,4 @@ logs
|
|||
ct.coverdata
|
||||
.idea/
|
||||
emqttd.iml
|
||||
_rel/
|
||||
|
|
604
bin/emqttd
604
bin/emqttd
|
@ -2,46 +2,21 @@
|
|||
# -*- tab-width:4;indent-tabs-mode:nil -*-
|
||||
# ex: ts=4 sw=4 et
|
||||
|
||||
# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is.
|
||||
if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
|
||||
POSIX_SHELL="true"
|
||||
export POSIX_SHELL
|
||||
# To support 'whoami' add /usr/ucb to path
|
||||
PATH=/usr/ucb:$PATH
|
||||
export PATH
|
||||
exec /usr/bin/ksh $0 "$@"
|
||||
fi
|
||||
unset POSIX_SHELL # clear it so if we invoke other scripts, they run as ksh as well
|
||||
set -e
|
||||
|
||||
RUNNER_SCRIPT_DIR={{runner_script_dir}}
|
||||
RUNNER_SCRIPT=${0##*/}
|
||||
|
||||
RUNNER_BASE_DIR={{runner_base_dir}}
|
||||
RUNNER_ETC_DIR={{runner_etc_dir}}
|
||||
RUNNER_LIB_DIR={{platform_lib_dir}}
|
||||
RUNNER_LOG_DIR={{runner_log_dir}}
|
||||
RUNNER_DATA_DIR=$RUNNER_BASE_DIR/data
|
||||
RUNNER_PLUGINS_DIR=$RUNNER_BASE_DIR/plugins
|
||||
|
||||
# Note the trailing slash on $PIPE_DIR/
|
||||
PIPE_DIR={{pipe_dir}}
|
||||
RUNNER_USER={{runner_user}}
|
||||
PLATFORM_DATA_DIR={{platform_data_dir}}
|
||||
SSL_DIST_CONFIG=$PLATFORM_DATA_DIR/ssl_distribution.args_file
|
||||
RIAK_VERSION="git"
|
||||
|
||||
WHOAMI=$(whoami)
|
||||
|
||||
# Make sure this script is running as the appropriate user
|
||||
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
|
||||
type sudo > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "sudo doesn't appear to be installed and your EUID isn't $RUNNER_USER" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2
|
||||
exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
|
||||
fi
|
||||
SCRIPT=$(readlink $0 || true)
|
||||
if [ -z $SCRIPT ]; then
|
||||
SCRIPT=$0
|
||||
fi;
|
||||
SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)"
|
||||
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||
REL_NAME="emqttd"
|
||||
REL_VSN="{{ rel_vsn }}"
|
||||
ERTS_VSN="{{ erts_vsn }}"
|
||||
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
|
||||
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
|
||||
ERL_OPTS="{{ erl_opts }}"
|
||||
RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_ROOT_DIR/log}"
|
||||
|
||||
# Warn the user if ulimit -n is less than 1024
|
||||
ULIMIT_F=`ulimit -n`
|
||||
|
@ -51,153 +26,231 @@ if [ "$ULIMIT_F" -lt 1024 ]; then
|
|||
echo "!!!!"
|
||||
fi
|
||||
|
||||
# Make sure CWD is set to runner base dir
|
||||
cd $RUNNER_BASE_DIR
|
||||
find_erts_dir() {
|
||||
__erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
|
||||
if [ -d "$__erts_dir" ]; then
|
||||
ERTS_DIR="$__erts_dir";
|
||||
ROOTDIR="$RELEASE_ROOT_DIR"
|
||||
else
|
||||
__erl="$(which erl)"
|
||||
code="io:format(\"~s\", [code:root_dir()]), halt()."
|
||||
__erl_root="$("$__erl" -noshell -eval "$code")"
|
||||
ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
|
||||
ROOTDIR="$__erl_root"
|
||||
fi
|
||||
}
|
||||
|
||||
# Get node pid
|
||||
relx_get_pid() {
|
||||
if output="$(relx_nodetool rpcterms os getpid)"
|
||||
then
|
||||
echo "$output" | sed -e 's/"//g'
|
||||
return 0
|
||||
else
|
||||
echo "$output"
|
||||
return 1
|
||||
fi
|
||||
}
|
||||
|
||||
relx_get_nodename() {
|
||||
id="longname$(relx_gen_id)-${NAME}"
|
||||
"$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
|
||||
}
|
||||
|
||||
# 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)"
|
||||
|
||||
# Setup remote shell command to control node
|
||||
exec "$BINDIR/erl" "$NAME_TYPE" "$id" -remsh "$NAME" -boot start_clean \
|
||||
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
|
||||
-setcookie "$COOKIE" -hidden -kernel net_ticktime $TICKTIME
|
||||
}
|
||||
|
||||
# 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
|
||||
|
||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
||||
-setcookie "$COOKIE" "$command" $@
|
||||
}
|
||||
|
||||
# Run an escript in the node's environment
|
||||
relx_escript() {
|
||||
shift; scriptpath="$1"; shift
|
||||
export RELEASE_ROOT_DIR
|
||||
|
||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/$scriptpath" $@
|
||||
}
|
||||
|
||||
# Output a start command for the last argument of run_erl
|
||||
relx_start_command() {
|
||||
printf "exec \"%s\" \"%s\"" "$RELEASE_ROOT_DIR/bin/$REL_NAME" \
|
||||
"$START_OPTION"
|
||||
}
|
||||
|
||||
# Use $CWD/vm.args if exists, otherwise releases/VSN/vm.args
|
||||
if [ -z "$VMARGS_PATH" ]; then
|
||||
if [ -f "$RELEASE_ROOT_DIR/vm.args" ]; then
|
||||
VMARGS_PATH="$RELEASE_ROOT_DIR/vm.args"
|
||||
else
|
||||
VMARGS_PATH="$REL_DIR/vm.args"
|
||||
fi
|
||||
fi
|
||||
|
||||
orig_vmargs_path="$VMARGS_PATH.orig"
|
||||
if [ $RELX_REPLACE_OS_VARS ]; then
|
||||
#Make sure we don't break dev mode by keeping the symbolic link to
|
||||
#the user's vm.args
|
||||
if [ ! -L "$orig_vmargs_path" ]; then
|
||||
#we're in copy mode, rename the vm.args file to vm.args.orig
|
||||
mv "$VMARGS_PATH" "$orig_vmargs_path"
|
||||
fi
|
||||
|
||||
awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$orig_vmargs_path" > "$VMARGS_PATH"
|
||||
else
|
||||
#We don't need to replace env. vars, just rename the
|
||||
#symlink vm.args.orig to vm.args, and keep it as a
|
||||
#symlink.
|
||||
if [ -L "$orig_vmargs_path" ]; then
|
||||
mv "$orig_vmargs_path" "$VMARGS_PATH"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Make sure log directory exists
|
||||
mkdir -p $RUNNER_LOG_DIR
|
||||
mkdir -p "$RUNNER_LOG_DIR"
|
||||
|
||||
# Make sure the data directory exists
|
||||
mkdir -p $PLATFORM_DATA_DIR
|
||||
# Use $CWD/sys.config if exists, otherwise releases/VSN/sys.config
|
||||
if [ -z "$RELX_CONFIG_PATH" ]; then
|
||||
if [ -f "$RELEASE_ROOT_DIR/sys.config" ]; then
|
||||
RELX_CONFIG_PATH="$RELEASE_ROOT_DIR/sys.config"
|
||||
else
|
||||
RELX_CONFIG_PATH="$REL_DIR/sys.config"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Warn the user if they don't have write permissions on the log dir
|
||||
if [ ! -w $RUNNER_LOG_DIR ]; then
|
||||
echo "!!!!"
|
||||
echo "!!!! WARNING: $RUNNER_LOG_DIR not writable; logs and crash dumps unavailable."
|
||||
echo "!!!!"
|
||||
orig_relx_config_path="$RELX_CONFIG_PATH.orig"
|
||||
if [ $RELX_REPLACE_OS_VARS ]; then
|
||||
#Make sure we don't break dev mode by keeping the symbolic link to
|
||||
#the user's sys.config
|
||||
if [ ! -L "$orig_relx_config_path" ]; then
|
||||
#We're in copy mode, rename sys.config to sys.config.orig
|
||||
mv "$RELX_CONFIG_PATH" "$orig_relx_config_path"
|
||||
fi
|
||||
|
||||
awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$orig_relx_config_path" > "$RELX_CONFIG_PATH"
|
||||
else
|
||||
#We don't need to replace env. vars, just rename the
|
||||
#symlink sys.config.orig to sys.config. Keep it as
|
||||
#a symlink.
|
||||
if [ -L "$orig_relx_config_path" ]; then
|
||||
mv "$orig_relx_config_path" "$RELX_CONFIG_PATH"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract the target node name from node.args
|
||||
NAME_ARG=`egrep '^\-s?name' $RUNNER_ETC_DIR/vm.args`
|
||||
NAME_ARG=$(egrep '^-s?name' "$VMARGS_PATH" || true)
|
||||
if [ -z "$NAME_ARG" ]; then
|
||||
echo "vm.args needs to have either -name or -sname parameter."
|
||||
exit 1
|
||||
fi
|
||||
NODE_NAME=${NAME_ARG##* }
|
||||
|
||||
# Extract the name type and name from the NAME_ARG for REMSH
|
||||
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
|
||||
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
|
||||
|
||||
PIPE_DIR="${PIPE_DIR:-/tmp/erl_pipes/$NAME/}"
|
||||
|
||||
# Extract the target cookie
|
||||
COOKIE_ARG=`grep '^\-setcookie' $RUNNER_ETC_DIR/vm.args`
|
||||
COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
|
||||
if [ -z "$COOKIE_ARG" ]; then
|
||||
echo "vm.args needs to have a -setcookie parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Identify the script name
|
||||
SCRIPT=`basename $0`
|
||||
# Extract cookie name from COOKIE_ARG
|
||||
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
|
||||
|
||||
# Parse out release and erts info
|
||||
START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data`
|
||||
ERTS_VSN=${START_ERL% *}
|
||||
APP_VSN=${START_ERL#* }
|
||||
find_erts_dir
|
||||
export ROOTDIR="$RELEASE_ROOT_DIR"
|
||||
export BINDIR="$ERTS_DIR/bin"
|
||||
export EMU="beam"
|
||||
export PROGNAME="erl"
|
||||
export LD_LIBRARY_PATH="$ERTS_DIR/lib:$LD_LIBRARY_PATH"
|
||||
ERTS_LIB_DIR="$ERTS_DIR/../lib"
|
||||
MNESIA_DATA_DIR="$ROOTDIR/data/mnesia/$NAME"
|
||||
|
||||
# Add ERTS bin dir to our path
|
||||
ERTS_PATH=$RUNNER_BASE_DIR/erts-$ERTS_VSN/bin
|
||||
cd "$ROOTDIR"
|
||||
|
||||
# Setup command to control the node
|
||||
NODETOOL="$ERTS_PATH/escript $ERTS_PATH/nodetool $NAME_ARG $COOKIE_ARG"
|
||||
NODETOOL_LITE="$ERTS_PATH/escript $ERTS_PATH/nodetool"
|
||||
|
||||
# Common functions
|
||||
|
||||
# Ping node without allowing nodetool to take stdin
|
||||
ping_node() {
|
||||
$NODETOOL ping < /dev/null
|
||||
}
|
||||
|
||||
# Set the PID global variable, return 1 on error
|
||||
get_pid() {
|
||||
PID=`$NODETOOL getpid < /dev/null`
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ]; then
|
||||
echo "Node is not running!"
|
||||
return 1
|
||||
fi
|
||||
|
||||
# don't allow empty or init pid's
|
||||
if [ -z $PID ] || [ "$PID" -le 1 ]; then
|
||||
return 1
|
||||
fi
|
||||
|
||||
return 0
|
||||
}
|
||||
|
||||
|
||||
# Scrape out SSL distribution config info from vm.args into $SSL_DIST_CONFIG
|
||||
rm -f $SSL_DIST_CONFIG
|
||||
sed -n '/Begin SSL distribution items/,/End SSL distribution items/p' \
|
||||
$RUNNER_ETC_DIR/vm.args > $SSL_DIST_CONFIG
|
||||
# User can specify an sname without @hostname
|
||||
# This will fail when creating remote shell
|
||||
# So here we check for @ and add @hostname if missing
|
||||
case $NAME in
|
||||
*@*)
|
||||
# Nothing to do
|
||||
;;
|
||||
*)
|
||||
NAME=$NAME@$(relx_get_nodename)
|
||||
;;
|
||||
esac
|
||||
|
||||
# Check the first argument for instructions
|
||||
case "$1" in
|
||||
start)
|
||||
# Make sure there is not already a node running
|
||||
RES=`ping_node`
|
||||
if [ "$RES" = "pong" ]; then
|
||||
echo "Node is already running!"
|
||||
exit 1
|
||||
fi
|
||||
# Sanity check the emqttd.config file
|
||||
RES=`$NODETOOL_LITE chkconfig $RUNNER_ETC_DIR/emqttd.config`
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error reading $RUNNER_ETC_DIR/emqttd.config"
|
||||
echo $RES
|
||||
exit 1
|
||||
fi
|
||||
HEART_COMMAND="$RUNNER_SCRIPT_DIR/$SCRIPT start"
|
||||
export HEART_COMMAND
|
||||
mkdir -p $PIPE_DIR
|
||||
$ERTS_PATH/run_erl -daemon $PIPE_DIR $RUNNER_LOG_DIR \
|
||||
"exec $RUNNER_SCRIPT_DIR/$SCRIPT console" 2>&1
|
||||
start|start_boot)
|
||||
|
||||
# Wait for the node to come up. We can't just ping it because
|
||||
# distributed erlang comes up for a second before emqttd crashes
|
||||
# (eg. in the case of an unwriteable disk). Once the node comes
|
||||
# up we check for the node watcher process. If that's running
|
||||
# then we assume things are good enough. This will at least let
|
||||
# the user know when emqttd is crashing right after startup.
|
||||
WAIT=${WAIT_FOR_ERLANG:-15}
|
||||
while [ $WAIT -gt 0 ]; do
|
||||
WAIT=`expr $WAIT - 1`
|
||||
sleep 1
|
||||
RES=`ping_node`
|
||||
if [ "$?" -ne 0 ]; then
|
||||
continue
|
||||
fi
|
||||
echo "emqttd is started successfully!"
|
||||
exit 0
|
||||
done
|
||||
echo "emqttd failed to start within ${WAIT_FOR_ERLANG:-15} seconds,"
|
||||
echo "see the output of 'emqttd console' for more information."
|
||||
echo "If you want to wait longer, set the environment variable"
|
||||
echo "WAIT_FOR_ERLANG to the number of seconds to wait."
|
||||
exit 1
|
||||
# Make sure there is not already a node running
|
||||
#RES=`$NODETOOL ping`
|
||||
#if [ "$RES" = "pong" ]; then
|
||||
# echo "Node is already running!"
|
||||
# exit 1
|
||||
#fi
|
||||
# Save this for later.
|
||||
CMD=$1
|
||||
case "$1" in
|
||||
start)
|
||||
shift
|
||||
START_OPTION="console"
|
||||
HEART_OPTION="start"
|
||||
;;
|
||||
start_boot)
|
||||
shift
|
||||
START_OPTION="console_boot"
|
||||
HEART_OPTION="start_boot"
|
||||
;;
|
||||
esac
|
||||
RUN_PARAM="$@"
|
||||
|
||||
# Set arguments for the heart command
|
||||
set -- "$SCRIPT_DIR/$REL_NAME" "$HEART_OPTION"
|
||||
[ "$RUN_PARAM" ] && set -- "$@" "$RUN_PARAM"
|
||||
|
||||
# Export the HEART_COMMAND
|
||||
HEART_COMMAND="$RELEASE_ROOT_DIR/bin/$REL_NAME $CMD"
|
||||
export HEART_COMMAND
|
||||
|
||||
mkdir -p "$PIPE_DIR"
|
||||
|
||||
"$BINDIR/run_erl" -daemon "$PIPE_DIR" "$RUNNER_LOG_DIR" \
|
||||
"$(relx_start_command)"
|
||||
;;
|
||||
|
||||
stop)
|
||||
UNAME_S=`uname -s`
|
||||
case $UNAME_S in
|
||||
Darwin)
|
||||
# Make sure we explicitly set this because iTerm.app doesn't for
|
||||
# some reason.
|
||||
COMMAND_MODE=unix2003
|
||||
esac
|
||||
|
||||
# Get the PID from nodetool
|
||||
get_pid
|
||||
GPR=$?
|
||||
if [ "$GPR" -ne 0 ] || [ -z $PID ]; then
|
||||
exit $GPR
|
||||
fi
|
||||
|
||||
# Tell nodetool to initiate a stop
|
||||
$NODETOOL stop
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ]; then
|
||||
exit $ES
|
||||
fi
|
||||
|
||||
# Wait for the node to completely stop...
|
||||
while `kill -s 0 $PID 2>/dev/null`;
|
||||
PID="$(relx_get_pid)"
|
||||
if ! relx_nodetool "stop"; then
|
||||
exit 1
|
||||
fi
|
||||
while $(kill -s 0 "$PID" 2>/dev/null);
|
||||
do
|
||||
sleep 1
|
||||
done
|
||||
|
@ -205,117 +258,214 @@ case "$1" in
|
|||
|
||||
restart)
|
||||
## Restart the VM without exiting the process
|
||||
$NODETOOL restart
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ]; then
|
||||
exit $ES
|
||||
if ! relx_nodetool "restart"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
reboot)
|
||||
## Restart the VM completely (uses heart to restart it)
|
||||
$NODETOOL reboot
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ]; then
|
||||
exit $ES
|
||||
if ! relx_nodetool "reboot"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
pid)
|
||||
## Get the VM's pid
|
||||
if ! relx_get_pid; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
ping)
|
||||
## See if the VM is alive
|
||||
ping_node
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ]; then
|
||||
exit $ES
|
||||
if ! relx_nodetool "ping"; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
escript)
|
||||
## Run an escript under the node's environment
|
||||
if ! relx_escript $@; then
|
||||
exit 1
|
||||
fi
|
||||
;;
|
||||
|
||||
attach)
|
||||
if [ "$2" = "-f" ]; then
|
||||
echo "Forcing connection..."
|
||||
else
|
||||
# Make sure a node is running
|
||||
RES=`ping_node`
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ]; then
|
||||
echo "Node is not running!"
|
||||
exit $ES
|
||||
fi
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift
|
||||
exec $ERTS_PATH/to_erl $PIPE_DIR
|
||||
exec "$BINDIR/to_erl" "$PIPE_DIR"
|
||||
;;
|
||||
|
||||
console)
|
||||
RES=`ping_node`
|
||||
if [ "$RES" = "pong" ]; then
|
||||
echo "Node is already running - use '$SCRIPT attach' instead"
|
||||
remote_console)
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
# Sanity check the emqttd.config file
|
||||
RES=`$NODETOOL_LITE chkconfig $RUNNER_ETC_DIR/emqttd.config`
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error reading $RUNNER_ETC_DIR/emqttd.config"
|
||||
echo $RES
|
||||
|
||||
shift
|
||||
relx_rem_sh
|
||||
;;
|
||||
|
||||
upgrade|downgrade|install)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Missing package argument"
|
||||
echo "Usage: $REL_NAME $1 {package base name}"
|
||||
echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
|
||||
"install" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
|
||||
;;
|
||||
|
||||
unpack)
|
||||
if [ -z "$2" ]; then
|
||||
echo "Missing package argument"
|
||||
echo "Usage: $REL_NAME $1 {package base name}"
|
||||
echo "NOTE {package base name} MUST NOT include the .tar.gz suffix"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
exec "$BINDIR/escript" "$ROOTDIR/bin/install_upgrade.escript" \
|
||||
"unpack" "$REL_NAME" "$NAME_TYPE" "$NAME" "$COOKIE" "$2"
|
||||
;;
|
||||
|
||||
console|console_clean|console_boot)
|
||||
# .boot file typically just $REL_NAME (ie, the app name)
|
||||
# however, for debugging, sometimes start_clean.boot is useful.
|
||||
# For e.g. 'setup', one may even want to name another boot script.
|
||||
case "$1" in
|
||||
console)
|
||||
if [ -f "$REL_DIR/$REL_NAME.boot" ]; then
|
||||
BOOTFILE="$REL_DIR/$REL_NAME"
|
||||
else
|
||||
BOOTFILE="$REL_DIR/start"
|
||||
fi
|
||||
;;
|
||||
console_clean)
|
||||
BOOTFILE="$ROOTDIR/bin/start_clean"
|
||||
;;
|
||||
console_boot)
|
||||
shift
|
||||
BOOTFILE="$1"
|
||||
shift
|
||||
;;
|
||||
esac
|
||||
# Setup beam-required vars
|
||||
ROOTDIR=$RUNNER_BASE_DIR
|
||||
ERL_LIBS=$ROOTDIR/plugins
|
||||
BINDIR=$ROOTDIR/erts-$ERTS_VSN/bin
|
||||
EMU=beam
|
||||
PROGNAME=`echo $0 | sed 's/.*\///'`
|
||||
# Setup Mnesia Dir
|
||||
MNESIA_DIR="$RUNNER_DATA_DIR/mnesia/$NODE_NAME"
|
||||
CMD="$BINDIR/erlexec -boot $RUNNER_BASE_DIR/releases/$APP_VSN/$SCRIPT \
|
||||
-embedded -config $RUNNER_ETC_DIR/emqttd.config \
|
||||
-pa $RUNNER_LIB_DIR/basho-patches \
|
||||
-mnesia dir "\"${MNESIA_DIR}\"" \
|
||||
-args_file $RUNNER_ETC_DIR/vm.args -- ${1+"$@"}"
|
||||
EMU="beam"
|
||||
PROGNAME="${0#*/}"
|
||||
|
||||
export EMU
|
||||
export ROOTDIR
|
||||
export ERL_LIBS
|
||||
export BINDIR
|
||||
export PROGNAME
|
||||
|
||||
# Store passed arguments since they will be erased by `set`
|
||||
ARGS="$@"
|
||||
|
||||
# Build an array of arguments to pass to exec later on
|
||||
# Build it here because this command will be used for logging.
|
||||
set -- "$BINDIR/erlexec" -boot "$BOOTFILE" -mode "$CODE_LOADING_MODE" \
|
||||
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
|
||||
-config "$RELX_CONFIG_PATH" \
|
||||
-mnesia dir "\"${MNESIA_DATA_DIR}\"" \
|
||||
-args_file "$VMARGS_PATH"
|
||||
|
||||
# Dump environment info for logging purposes
|
||||
echo "Exec: $CMD"
|
||||
echo "Exec: $@" -- ${1+$ARGS}
|
||||
echo "Root: $ROOTDIR"
|
||||
|
||||
# Log the startup
|
||||
logger -t "$SCRIPT[$$]" "Starting up"
|
||||
echo "$RELEASE_ROOT_DIR"
|
||||
logger -t "$REL_NAME[$$]" "Starting up"
|
||||
|
||||
# Start the VM
|
||||
exec $CMD
|
||||
exec "$@" -- ${1+$ARGS}
|
||||
;;
|
||||
chkconfig)
|
||||
RES=`$NODETOOL_LITE chkconfig $RUNNER_ETC_DIR/emqttd.config`
|
||||
if [ $? != 0 ]; then
|
||||
echo "Error reading $RUNNER_ETC_DIR/emqttd.config"
|
||||
echo $RES
|
||||
|
||||
foreground)
|
||||
# start up the release in the foreground for use by runit
|
||||
# or other supervision services
|
||||
|
||||
[ -f "$REL_DIR/$REL_NAME.boot" ] && BOOTFILE="$REL_NAME" || BOOTFILE=start
|
||||
FOREGROUNDOPTIONS="-noshell -noinput +Bd"
|
||||
|
||||
# Setup beam-required vars
|
||||
EMU=beam
|
||||
PROGNAME="${0#*/}"
|
||||
|
||||
export EMU
|
||||
export PROGNAME
|
||||
|
||||
# Store passed arguments since they will be erased by `set`
|
||||
ARGS="$@"
|
||||
|
||||
# Build an array of arguments to pass to exec later on
|
||||
# Build it here because this command will be used for logging.
|
||||
set -- "$BINDIR/erlexec" $FOREGROUNDOPTIONS \
|
||||
-boot "$REL_DIR/$BOOTFILE" -mode "$CODE_LOADING_MODE" -config "$RELX_CONFIG_PATH" \
|
||||
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR" \
|
||||
-mnesia dir "\"${MNESIA_DATA_DIR}\"" \
|
||||
-args_file "$VMARGS_PATH"
|
||||
|
||||
# Dump environment info for logging purposes
|
||||
echo "Exec: $@" -- ${1+$ARGS}
|
||||
echo "Root: $ROOTDIR"
|
||||
|
||||
# Start the VM
|
||||
exec "$@" -- ${1+$ARGS}
|
||||
;;
|
||||
rpc)
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
echo "config is OK"
|
||||
;;
|
||||
escript)
|
||||
|
||||
shift
|
||||
$ERTS_PATH/escript "$@"
|
||||
|
||||
relx_nodetool rpc $@
|
||||
;;
|
||||
version)
|
||||
echo $RIAK_VERSION
|
||||
;;
|
||||
getpid)
|
||||
# Get the PID from nodetool
|
||||
get_pid
|
||||
ES=$?
|
||||
if [ "$ES" -ne 0 ] || [ -z $PID ]; then
|
||||
exit $ES
|
||||
rpcterms)
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
echo $PID
|
||||
|
||||
shift
|
||||
|
||||
relx_nodetool rpcterms $@
|
||||
;;
|
||||
eval)
|
||||
# Make sure a node IS running
|
||||
if ! relx_nodetool "ping" > /dev/null; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
shift
|
||||
relx_nodetool "eval" $@
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPT {start|stop|restart|reboot|ping|console|attach|chkconfig|escript|version|getpid}"
|
||||
echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|escript|rpc|rpcterms|eval}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
|
124
bin/emqttd_ctl
124
bin/emqttd_ctl
|
@ -2,90 +2,82 @@
|
|||
# -*- tab-width:4;indent-tabs-mode:nil -*-
|
||||
# ex: ts=4 sw=4 et
|
||||
|
||||
# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is.
|
||||
if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
|
||||
POSIX_SHELL="true"
|
||||
export POSIX_SHELL
|
||||
# To support 'whoami' add /usr/ucb to path
|
||||
PATH=/usr/ucb:$PATH
|
||||
export PATH
|
||||
exec /usr/bin/ksh $0 "$@"
|
||||
fi
|
||||
unset POSIX_SHELL # clear it so if we invoke other scripts, they run as ksh as well
|
||||
set -e
|
||||
|
||||
RUNNER_SCRIPT_DIR={{runner_script_dir}}
|
||||
RUNNER_SCRIPT=${0##*/}
|
||||
SCRIPT=$(readlink $0 || true)
|
||||
if [ -z $SCRIPT ]; then
|
||||
SCRIPT=$0
|
||||
fi;
|
||||
SCRIPT_DIR="$(cd `dirname "$SCRIPT"` && pwd -P)"
|
||||
RELEASE_ROOT_DIR="$(cd "$SCRIPT_DIR/.." && pwd -P)"
|
||||
REL_NAME="emqttd"
|
||||
REL_VSN="{{ rel_vsn }}"
|
||||
ERTS_VSN="{{ erts_vsn }}"
|
||||
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
|
||||
ERL_OPTS="{{ erl_opts }}"
|
||||
RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-$RELEASE_ROOT_DIR/log}"
|
||||
|
||||
RUNNER_BASE_DIR={{runner_base_dir}}
|
||||
RUNNER_ETC_DIR={{runner_etc_dir}}
|
||||
RUNNER_LIB_DIR={{platform_lib_dir}}
|
||||
RUNNER_LOG_DIR={{runner_log_dir}}
|
||||
RUNNER_USER={{runner_user}}
|
||||
|
||||
WHOAMI=$(whoami)
|
||||
|
||||
# Make sure this script is running as the appropriate user
|
||||
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
|
||||
type sudo > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "sudo doesn't appear to be installed and your EUID isn't $RUNNER_USER" 1>&2
|
||||
exit 1
|
||||
find_erts_dir() {
|
||||
__erts_dir="$RELEASE_ROOT_DIR/erts-$ERTS_VSN"
|
||||
if [ -d "$__erts_dir" ]; then
|
||||
ERTS_DIR="$__erts_dir";
|
||||
ROOTDIR="$RELEASE_ROOT_DIR"
|
||||
else
|
||||
__erl="$(which erl)"
|
||||
code="io:format(\"~s\", [code:root_dir()]), halt()."
|
||||
__erl_root="$("$__erl" -noshell -eval "$code")"
|
||||
ERTS_DIR="$__erl_root/erts-$ERTS_VSN"
|
||||
ROOTDIR="$__erl_root"
|
||||
fi
|
||||
echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2
|
||||
exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
|
||||
fi
|
||||
}
|
||||
|
||||
# Make sure CWD is set to runner base dir
|
||||
cd $RUNNER_BASE_DIR
|
||||
relx_get_nodename() {
|
||||
id="longname$(relx_gen_id)-${NAME}"
|
||||
"$BINDIR/erl" -boot start_clean -eval '[Host] = tl(string:tokens(atom_to_list(node()),"@")), io:format("~s~n", [Host]), halt()' -noshell ${NAME_TYPE} $id
|
||||
}
|
||||
|
||||
# Control a node
|
||||
relx_nodetool() {
|
||||
command="$1"; shift
|
||||
|
||||
"$ERTS_DIR/bin/escript" "$ROOTDIR/bin/nodetool" "$NAME_TYPE" "$NAME" \
|
||||
-setcookie "$COOKIE" "$command" $@
|
||||
}
|
||||
|
||||
# Use $CWD/vm.args if exists, otherwise releases/VSN/vm.args
|
||||
if [ -z "$VMARGS_PATH" ]; then
|
||||
if [ -f "$RELEASE_ROOT_DIR/vm.args" ]; then
|
||||
VMARGS_PATH="$RELEASE_ROOT_DIR/vm.args"
|
||||
else
|
||||
VMARGS_PATH="$REL_DIR/vm.args"
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract the target node name from node.args
|
||||
NAME_ARG=`egrep "^ *-s?name" $RUNNER_ETC_DIR/vm.args`
|
||||
NAME_ARG=$(egrep '^-s?name' "$VMARGS_PATH" || true)
|
||||
if [ -z "$NAME_ARG" ]; then
|
||||
echo "vm.args needs to have either -name or -sname parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Learn how to specify node name for connection from remote nodes
|
||||
echo "$NAME_ARG" | grep '^-sname' > /dev/null 2>&1
|
||||
if [ "X$?" = "X0" ]; then
|
||||
NAME_PARAM="-sname"
|
||||
NAME_HOST=""
|
||||
else
|
||||
NAME_PARAM="-name"
|
||||
echo "$NAME_ARG" | grep '@.*' > /dev/null 2>&1
|
||||
if [ "X$?" = "X0" ]; then
|
||||
NAME_HOST=`echo "${NAME_ARG}" | sed -e 's/.*\(@.*\)$/\1/'`
|
||||
else
|
||||
NAME_HOST=""
|
||||
fi
|
||||
fi
|
||||
# Extract the name type and name from the NAME_ARG for REMSH
|
||||
NAME_TYPE="$(echo "$NAME_ARG" | awk '{print $1}')"
|
||||
NAME="$(echo "$NAME_ARG" | awk '{print $2}')"
|
||||
|
||||
# Extract the target cookie
|
||||
COOKIE_ARG=`grep '\-setcookie' $RUNNER_ETC_DIR/vm.args`
|
||||
COOKIE_ARG="$(grep '^-setcookie' "$VMARGS_PATH" || true)"
|
||||
if [ -z "$COOKIE_ARG" ]; then
|
||||
echo "vm.args needs to have a -setcookie parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Identify the script name
|
||||
SCRIPT=`basename $0`
|
||||
# Extract cookie name from COOKIE_ARG
|
||||
COOKIE="$(echo "$COOKIE_ARG" | awk '{print $2}')"
|
||||
|
||||
# Parse out release and erts info
|
||||
START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data`
|
||||
ERTS_VSN=${START_ERL% *}
|
||||
APP_VSN=${START_ERL#* }
|
||||
find_erts_dir
|
||||
export ROOTDIR="$RELEASE_ROOT_DIR"
|
||||
export BINDIR="$ERTS_DIR/bin"
|
||||
cd "$ROOTDIR"
|
||||
|
||||
# Add ERTS bin dir to our path
|
||||
ERTS_PATH=$RUNNER_BASE_DIR/erts-$ERTS_VSN/bin
|
||||
|
||||
# Setup command to control the node
|
||||
NODETOOL="$ERTS_PATH/escript $ERTS_PATH/nodetool $NAME_ARG $COOKIE_ARG"
|
||||
|
||||
RES=`$NODETOOL ping`
|
||||
if [ "$RES" != "pong" ]; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
$NODETOOL rpc emqttd_ctl run $@
|
||||
relx_nodetool rpc emqttd_ctl run $@
|
||||
|
||||
|
|
117
bin/emqttd_top
117
bin/emqttd_top
|
@ -1,117 +0,0 @@
|
|||
#!/bin/sh
|
||||
# -*- tab-width:4;indent-tabs-mode:nil -*-
|
||||
# ex: ts=4 sw=4 et
|
||||
|
||||
# /bin/sh on Solaris is not a POSIX compatible shell, but /usr/bin/ksh is.
|
||||
if [ `uname -s` = 'SunOS' -a "${POSIX_SHELL}" != "true" ]; then
|
||||
POSIX_SHELL="true"
|
||||
export POSIX_SHELL
|
||||
# To support 'whoami' add /usr/ucb to path
|
||||
PATH=/usr/ucb:$PATH
|
||||
export PATH
|
||||
exec /usr/bin/ksh $0 "$@"
|
||||
fi
|
||||
unset POSIX_SHELL # clear it so if we invoke other scripts, they run as ksh as well
|
||||
|
||||
RUNNER_SCRIPT_DIR={{runner_script_dir}}
|
||||
RUNNER_SCRIPT=${0##*/}
|
||||
|
||||
RUNNER_BASE_DIR={{runner_base_dir}}
|
||||
RUNNER_ETC_DIR={{runner_etc_dir}}
|
||||
RUNNER_LIB_DIR={{platform_lib_dir}}
|
||||
RUNNER_USER={{runner_user}}
|
||||
|
||||
WHOAMI=$(whoami)
|
||||
|
||||
# Make sure this script is running as the appropriate user
|
||||
if ([ "$RUNNER_USER" ] && [ "x$WHOAMI" != "x$RUNNER_USER" ]); then
|
||||
type sudo > /dev/null 2>&1
|
||||
if [ $? -ne 0 ]; then
|
||||
echo "sudo doesn't appear to be installed and your EUID isn't $RUNNER_USER" 1>&2
|
||||
exit 1
|
||||
fi
|
||||
echo "Attempting to restart script through sudo -H -u $RUNNER_USER" >&2
|
||||
exec sudo -H -u $RUNNER_USER -i $RUNNER_SCRIPT_DIR/$RUNNER_SCRIPT $@
|
||||
fi
|
||||
|
||||
# Make sure CWD is set to runner base dir
|
||||
cd $RUNNER_BASE_DIR
|
||||
|
||||
# Extract the target node name from node.args
|
||||
NAME_ARG=`egrep "^ *-s?name" $RUNNER_ETC_DIR/vm.args`
|
||||
if [ -z "$NAME_ARG" ]; then
|
||||
echo "vm.args needs to have either -name or -sname parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Learn how to specify node name for connection from remote nodes
|
||||
echo "$NAME_ARG" | grep '^-sname' > /dev/null 2>&1
|
||||
if [ "X$?" = "X0" ]; then
|
||||
NAME_PARAM="-sname"
|
||||
NAME_HOST=""
|
||||
else
|
||||
NAME_PARAM="-name"
|
||||
echo "$NAME_ARG" | grep '@.*' > /dev/null 2>&1
|
||||
if [ "X$?" = "X0" ]; then
|
||||
NAME_HOST=`echo "${NAME_ARG}" | sed -e 's/.*\(@.*\)$/\1/'`
|
||||
else
|
||||
NAME_HOST=""
|
||||
fi
|
||||
fi
|
||||
|
||||
# Extract the target cookie
|
||||
COOKIE_ARG=`grep '\-setcookie' $RUNNER_ETC_DIR/vm.args`
|
||||
if [ -z "$COOKIE_ARG" ]; then
|
||||
echo "vm.args needs to have a -setcookie parameter."
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Identify the script name
|
||||
SCRIPT=`basename $0`
|
||||
|
||||
# Parse out release and erts info
|
||||
START_ERL=`cat $RUNNER_BASE_DIR/releases/start_erl.data`
|
||||
ERTS_VSN=${START_ERL% *}
|
||||
APP_VSN=${START_ERL#* }
|
||||
|
||||
# Add ERTS bin dir to our path
|
||||
ERTS_PATH=$RUNNER_BASE_DIR/erts-$ERTS_VSN/bin
|
||||
|
||||
NODE_NAME=${NAME_ARG#* }
|
||||
|
||||
# Setup command to control the node
|
||||
NODETOOL="$ERTS_PATH/escript $ERTS_PATH/nodetool $NAME_ARG $COOKIE_ARG"
|
||||
|
||||
RES=`$NODETOOL ping`
|
||||
if [ "$RES" != "pong" ]; then
|
||||
echo "Node is not running!"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
case "$1" in
|
||||
runtime)
|
||||
SORTBY="runtime"
|
||||
;;
|
||||
reductions)
|
||||
SORTBY="reductions"
|
||||
;;
|
||||
memory)
|
||||
SORTBY="memory"
|
||||
;;
|
||||
msg_q)
|
||||
SORTBY="msg_q"
|
||||
;;
|
||||
*)
|
||||
echo "Usage: $SCRIPT {runtime | reductions | memory | msg_q}"
|
||||
exit 1
|
||||
;;
|
||||
esac
|
||||
|
||||
MYPID=$$
|
||||
ETOP_ARGS="-sort $SORTBY -interval 10 -lines 50 -tracing off"
|
||||
$ERTS_PATH/erl -noshell -noinput \
|
||||
-pa $RUNNER_LIB_DIR/basho-patches \
|
||||
-hidden $NAME_PARAM emqttd_top$MYPID$NAME_HOST $COOKIE_ARG \
|
||||
-s etop -s erlang halt -output text \
|
||||
-node $NODE_NAME $ETOP_ARGS
|
||||
|
|
@ -1,44 +0,0 @@
|
|||
#!/usr/bin/env escript
|
||||
%%! -noshell -noinput
|
||||
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% ex: ft=erlang ts=4 sw=4 et
|
||||
|
||||
-define(TIMEOUT, 60000).
|
||||
-define(INFO(Fmt,Args), io:format(Fmt,Args)).
|
||||
|
||||
main([NodeName, Cookie, ReleasePackage]) ->
|
||||
TargetNode = start_distribution(NodeName, Cookie),
|
||||
{ok, Vsn} = rpc:call(TargetNode, release_handler, unpack_release,
|
||||
[ReleasePackage], ?TIMEOUT),
|
||||
?INFO("Unpacked Release ~p~n", [Vsn]),
|
||||
{ok, OtherVsn, Desc} = rpc:call(TargetNode, release_handler,
|
||||
check_install_release, [Vsn], ?TIMEOUT),
|
||||
{ok, OtherVsn, Desc} = rpc:call(TargetNode, release_handler,
|
||||
install_release, [Vsn], ?TIMEOUT),
|
||||
?INFO("Installed Release ~p~n", [Vsn]),
|
||||
ok = rpc:call(TargetNode, release_handler, make_permanent, [Vsn], ?TIMEOUT),
|
||||
?INFO("Made Release ~p Permanent~n", [Vsn]);
|
||||
main(_) ->
|
||||
init:stop(1).
|
||||
|
||||
start_distribution(NodeName, Cookie) ->
|
||||
MyNode = make_script_node(NodeName),
|
||||
{ok, _Pid} = net_kernel:start([MyNode, shortnames]),
|
||||
erlang:set_cookie(node(), list_to_atom(Cookie)),
|
||||
TargetNode = make_target_node(NodeName),
|
||||
case {net_kernel:hidden_connect_node(TargetNode),
|
||||
net_adm:ping(TargetNode)} of
|
||||
{true, pong} ->
|
||||
ok;
|
||||
{_, pang} ->
|
||||
io:format("Node ~p not responding to pings.\n", [TargetNode]),
|
||||
init:stop(1)
|
||||
end,
|
||||
TargetNode.
|
||||
|
||||
make_target_node(Node) ->
|
||||
[_, Host] = string:tokens(atom_to_list(node()), "@"),
|
||||
list_to_atom(lists:concat([Node, "@", Host])).
|
||||
|
||||
make_script_node(Node) ->
|
||||
list_to_atom(lists:concat([Node, "_upgrader_", os:getpid()])).
|
|
@ -0,0 +1,143 @@
|
|||
#!/usr/bin/env escript
|
||||
%%! -noshell -noinput
|
||||
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% ex: ft=erlang ts=4 sw=4 et
|
||||
|
||||
-define(TIMEOUT, 300000).
|
||||
-define(INFO(Fmt,Args), io:format(Fmt,Args)).
|
||||
|
||||
%% Unpack or upgrade to a new tar.gz release
|
||||
main(["unpack", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) ->
|
||||
TargetNode = start_distribution(NodeName, NameTypeArg, Cookie),
|
||||
WhichReleases = which_releases(TargetNode),
|
||||
Version = parse_version(VersionArg),
|
||||
case proplists:get_value(Version, WhichReleases) of
|
||||
undefined ->
|
||||
%% not installed, so unpack tarball:
|
||||
?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]),
|
||||
ReleasePackage = Version ++ "/" ++ RelName,
|
||||
case rpc:call(TargetNode, release_handler, unpack_release,
|
||||
[ReleasePackage], ?TIMEOUT) of
|
||||
{ok, Vsn} ->
|
||||
?INFO("Unpacked successfully: ~p~n", [Vsn]);
|
||||
{error, UnpackReason} ->
|
||||
print_existing_versions(TargetNode),
|
||||
?INFO("Unpack failed: ~p~n",[UnpackReason]),
|
||||
erlang:halt(2)
|
||||
end;
|
||||
old ->
|
||||
%% no need to unpack, has been installed previously
|
||||
?INFO("Release ~s is marked old, switching to it.~n",[Version]);
|
||||
unpacked ->
|
||||
?INFO("Release ~s is already unpacked, now installing.~n",[Version]);
|
||||
current ->
|
||||
?INFO("Release ~s is already installed and current. Making permanent.~n",[Version]);
|
||||
permanent ->
|
||||
?INFO("Release ~s is already installed, and set permanent.~n",[Version])
|
||||
end;
|
||||
main(["install", RelName, NameTypeArg, NodeName, Cookie, VersionArg]) ->
|
||||
TargetNode = start_distribution(NodeName, NameTypeArg, Cookie),
|
||||
WhichReleases = which_releases(TargetNode),
|
||||
Version = parse_version(VersionArg),
|
||||
case proplists:get_value(Version, WhichReleases) of
|
||||
undefined ->
|
||||
%% not installed, so unpack tarball:
|
||||
?INFO("Release ~s not found, attempting to unpack releases/~s/~s.tar.gz~n",[Version,Version,RelName]),
|
||||
ReleasePackage = Version ++ "/" ++ RelName,
|
||||
case rpc:call(TargetNode, release_handler, unpack_release,
|
||||
[ReleasePackage], ?TIMEOUT) of
|
||||
{ok, Vsn} ->
|
||||
?INFO("Unpacked successfully: ~p~n", [Vsn]),
|
||||
install_and_permafy(TargetNode, RelName, Vsn);
|
||||
{error, UnpackReason} ->
|
||||
print_existing_versions(TargetNode),
|
||||
?INFO("Unpack failed: ~p~n",[UnpackReason]),
|
||||
erlang:halt(2)
|
||||
end;
|
||||
old ->
|
||||
%% no need to unpack, has been installed previously
|
||||
?INFO("Release ~s is marked old, switching to it.~n",[Version]),
|
||||
install_and_permafy(TargetNode, RelName, Version);
|
||||
unpacked ->
|
||||
?INFO("Release ~s is already unpacked, now installing.~n",[Version]),
|
||||
install_and_permafy(TargetNode, RelName, Version);
|
||||
current -> %% installed and in-use, just needs to be permanent
|
||||
?INFO("Release ~s is already installed and current. Making permanent.~n",[Version]),
|
||||
permafy(TargetNode, RelName, Version);
|
||||
permanent ->
|
||||
?INFO("Release ~s is already installed, and set permanent.~n",[Version])
|
||||
end;
|
||||
main(_) ->
|
||||
erlang:halt(1).
|
||||
|
||||
parse_version(V) when is_list(V) ->
|
||||
hd(string:tokens(V,"/")).
|
||||
|
||||
install_and_permafy(TargetNode, RelName, Vsn) ->
|
||||
case rpc:call(TargetNode, release_handler, check_install_release, [Vsn], ?TIMEOUT) of
|
||||
{ok, _OtherVsn, _Desc} ->
|
||||
ok;
|
||||
{error, Reason} ->
|
||||
?INFO("ERROR: release_handler:check_install_release failed: ~p~n",[Reason]),
|
||||
erlang:halt(3)
|
||||
end,
|
||||
case rpc:call(TargetNode, release_handler, install_release, [Vsn], ?TIMEOUT) of
|
||||
{ok, _, _} ->
|
||||
?INFO("Installed Release: ~s~n", [Vsn]),
|
||||
permafy(TargetNode, RelName, Vsn),
|
||||
ok;
|
||||
{error, {no_such_release, Vsn}} ->
|
||||
VerList =
|
||||
iolist_to_binary(
|
||||
[io_lib:format("* ~s\t~s~n",[V,S]) || {V,S} <- which_releases(TargetNode)]),
|
||||
?INFO("Installed versions:~n~s", [VerList]),
|
||||
?INFO("ERROR: Unable to revert to '~s' - not installed.~n", [Vsn]),
|
||||
erlang:halt(2)
|
||||
end.
|
||||
|
||||
permafy(TargetNode, RelName, Vsn) ->
|
||||
ok = rpc:call(TargetNode, release_handler, make_permanent, [Vsn], ?TIMEOUT),
|
||||
file:copy(filename:join(["bin", RelName++"-"++Vsn]),
|
||||
filename:join(["bin", RelName])),
|
||||
?INFO("Made release permanent: ~p~n", [Vsn]),
|
||||
ok.
|
||||
|
||||
which_releases(TargetNode) ->
|
||||
R = rpc:call(TargetNode, release_handler, which_releases, [], ?TIMEOUT),
|
||||
[ {V, S} || {_,V,_, S} <- R ].
|
||||
|
||||
print_existing_versions(TargetNode) ->
|
||||
VerList = iolist_to_binary([
|
||||
io_lib:format("* ~s\t~s~n",[V,S])
|
||||
|| {V,S} <- which_releases(TargetNode) ]),
|
||||
?INFO("Installed versions:~n~s", [VerList]).
|
||||
|
||||
start_distribution(NodeName, NameTypeArg, Cookie) ->
|
||||
MyNode = make_script_node(NodeName),
|
||||
{ok, _Pid} = net_kernel:start([MyNode, get_name_type(NameTypeArg)]),
|
||||
erlang:set_cookie(node(), list_to_atom(Cookie)),
|
||||
TargetNode = list_to_atom(NodeName),
|
||||
case {net_kernel:connect_node(TargetNode),
|
||||
net_adm:ping(TargetNode)} of
|
||||
{true, pong} ->
|
||||
ok;
|
||||
{_, pang} ->
|
||||
io:format("Node ~p not responding to pings.\n", [TargetNode]),
|
||||
erlang:halt(1)
|
||||
end,
|
||||
{ok, Cwd} = file:get_cwd(),
|
||||
ok = rpc:call(TargetNode, file, set_cwd, [Cwd], ?TIMEOUT),
|
||||
TargetNode.
|
||||
|
||||
make_script_node(Node) ->
|
||||
[Name, Host] = string:tokens(Node, "@"),
|
||||
list_to_atom(lists:concat([Name, "_upgrader_", os:getpid(), "@", Host])).
|
||||
|
||||
%% get name type from arg
|
||||
get_name_type(NameTypeArg) ->
|
||||
case NameTypeArg of
|
||||
"-sname" ->
|
||||
shortnames;
|
||||
_ ->
|
||||
longnames
|
||||
end.
|
44
bin/nodetool
44
bin/nodetool
|
@ -1,5 +1,4 @@
|
|||
#!/usr/bin/env escript
|
||||
|
||||
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% ex: ft=erlang ts=4 sw=4 et
|
||||
%% -------------------------------------------------------------------
|
||||
|
@ -38,8 +37,8 @@ main(Args) ->
|
|||
{error, {Line, Mod, Term}} ->
|
||||
io:format(standard_error, ["Error on line ", file:format_error({Line, Mod, Term}), "\n"], []),
|
||||
halt(1);
|
||||
{error, R} ->
|
||||
io:format(standard_error, ["Error reading config file: ", file:format_error(R), "\n"], []),
|
||||
{error, Error} ->
|
||||
io:format(standard_error, ["Error reading config file: ", file:format_error(Error), "\n"], []),
|
||||
halt(1)
|
||||
end;
|
||||
_ ->
|
||||
|
@ -94,20 +93,48 @@ main(Args) ->
|
|||
end;
|
||||
["rpcterms", Module, Function, ArgsAsString] ->
|
||||
case rpc:call(TargetNode, list_to_atom(Module), list_to_atom(Function),
|
||||
consult(ArgsAsString), 60000) of
|
||||
consult(lists:flatten(ArgsAsString)), 60000) of
|
||||
{badrpc, Reason} ->
|
||||
io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
|
||||
halt(1);
|
||||
Other ->
|
||||
io:format("~p\n", [Other])
|
||||
end;
|
||||
["eval" | ListOfArgs] ->
|
||||
% shells may process args into more than one, and end up stripping
|
||||
% spaces, so this converts all of that to a single string to parse
|
||||
String = binary_to_list(
|
||||
list_to_binary(
|
||||
string:join(ListOfArgs," ")
|
||||
)
|
||||
),
|
||||
|
||||
% then just as a convenience to users, if they forgot a trailing
|
||||
% '.' add it for them.
|
||||
Normalized =
|
||||
case lists:reverse(String) of
|
||||
[$. | _] -> String;
|
||||
R -> lists:reverse([$. | R])
|
||||
end,
|
||||
|
||||
% then scan and parse the string
|
||||
{ok, Scanned, _} = erl_scan:string(Normalized),
|
||||
{ok, Parsed } = erl_parse:parse_exprs(Scanned),
|
||||
|
||||
% and evaluate it on the remote node
|
||||
case rpc:call(TargetNode, erl_eval, exprs, [Parsed, [] ]) of
|
||||
{value, Value, _} ->
|
||||
io:format ("~p\n",[Value]);
|
||||
{badrpc, Reason} ->
|
||||
io:format("RPC to ~p failed: ~p\n", [TargetNode, Reason]),
|
||||
halt(1)
|
||||
end;
|
||||
Other ->
|
||||
io:format("Other: ~p\n", [Other]),
|
||||
io:format("Usage: nodetool {chkconfig|getpid|ping|stop|restart|reboot|rpc|rpc_infinity|rpcterms}\n")
|
||||
io:format("Usage: nodetool {chkconfig|getpid|ping|stop|restart|reboot|rpc|rpc_infinity|rpcterms|eval [Terms]} [RPC]\n")
|
||||
end,
|
||||
net_kernel:stop().
|
||||
|
||||
|
||||
process_args([], Acc, TargetNode) ->
|
||||
{lists:reverse(Acc), TargetNode};
|
||||
process_args(["-setcookie", Cookie | Rest], Acc, TargetNode) ->
|
||||
|
@ -126,7 +153,7 @@ process_args([Arg | Rest], Acc, Opts) ->
|
|||
|
||||
|
||||
start_epmd() ->
|
||||
[] = os:cmd(epmd_path() ++ " -daemon"),
|
||||
[] = os:cmd("\"" ++ epmd_path() ++ "\" -daemon"),
|
||||
ok.
|
||||
|
||||
epmd_path() ->
|
||||
|
@ -163,7 +190,6 @@ append_node_suffix(Name, Suffix) ->
|
|||
list_to_atom(lists:concat([Node, Suffix, os:getpid()]))
|
||||
end.
|
||||
|
||||
|
||||
%%
|
||||
%% Given a string or binary, parse it into a list of terms, ala file:consult/0
|
||||
%%
|
||||
|
@ -188,7 +214,6 @@ consult(Cont, Str, Acc) ->
|
|||
consult(Cont1, eof, Acc)
|
||||
end.
|
||||
|
||||
|
||||
%%
|
||||
%% Validation functions for checking the emqttd.config
|
||||
%%
|
||||
|
@ -211,4 +236,3 @@ print_issue({warning, Warning}) ->
|
|||
print_issue({error, Error}) ->
|
||||
io:format(standard_error, "Error in emqttd.config: ~s~n", [Error]).
|
||||
|
||||
|
||||
|
|
|
@ -1,3 +1,27 @@
|
|||
%%===================================================================
|
||||
%%
|
||||
%% Config file for emqttd 2.0
|
||||
%%
|
||||
%% Erlang Term Syntax:
|
||||
%%
|
||||
%% {}: Tuple, usually {Key, Value}
|
||||
%% []: List, seperated by comma
|
||||
%% %%: comment
|
||||
%%
|
||||
%%===================================================================
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Protocol
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Max ClientId Length Allowed.
|
||||
{mqtt_max_clientid_len, 512}.
|
||||
|
||||
%% Max Packet Size Allowed, 64K by default.
|
||||
{mqtt_max_packet_size, 65536}.
|
||||
|
||||
%% Client Idle Timeout.
|
||||
{mqtt_client_idle_timeout, 30}. % Second
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Authentication
|
||||
|
@ -11,7 +35,7 @@
|
|||
{auth, username, [{passwd, "etc/passwd.conf"}, {passwd_hash, plain}]}.
|
||||
|
||||
%% Authentication with clientId
|
||||
{auth, clientid, [{clients, "etc/client.config"}, {password, no}]}.
|
||||
{auth, clientid, [{config, "etc/client.config"}, {password, no}]}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% ACL
|
||||
|
@ -42,25 +66,12 @@
|
|||
{retained_max_playload_size, 65536}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Protocol
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Max ClientId Length Allowed.
|
||||
{mqtt_max_clientid_len, 512}.
|
||||
|
||||
%% Max Packet Size Allowed, 64K by default.
|
||||
{mqtt_max_packet_size, 65536}.
|
||||
|
||||
%% Socket Idle Timeout.
|
||||
{mqtt_client_idle_timeout, 30}. % Seconds
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% MQTT Session
|
||||
%% Session
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Max number of QoS 1 and 2 messages that can be “inflight” at one time.
|
||||
%% 0 means no limit
|
||||
{session_max_inflight, 100}.
|
||||
{session_max_inflight, 100}.
|
||||
|
||||
%% Retry interval for redelivering QoS1/2 messages.
|
||||
{session_unack_retry_interval, 60}.
|
||||
|
@ -101,7 +112,13 @@
|
|||
{queue_qos0, true}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Listeners
|
||||
%% Zone
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
{zone, admin, []}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Listener
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Plain MQTT
|
||||
|
@ -112,6 +129,9 @@
|
|||
%% Maximum number of concurrent clients
|
||||
{max_clients, 512},
|
||||
|
||||
%% Mount point prefix
|
||||
%% {mount_point, "prefix/"},
|
||||
|
||||
%% Socket Access Control
|
||||
{access, [{allow, all}]},
|
||||
|
||||
|
@ -132,7 +152,7 @@
|
|||
]}
|
||||
]}.
|
||||
|
||||
%% MQTT SSL
|
||||
%% MQTT/SSL
|
||||
{listener, mqtts, 8883, [
|
||||
%% Size of acceptor pool
|
||||
{acceptors, 4},
|
||||
|
@ -179,8 +199,12 @@
|
|||
%% PubSub and Router. Default should be scheduler numbers.
|
||||
{pubsub_pool_size, 8}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Routing
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Route aging time(seconds)
|
||||
{pubsub_routing_age, 5}.
|
||||
{routing_age, 5}.
|
||||
|
||||
%%--------------------------------------------------------------------
|
||||
%% Bridge
|
||||
|
@ -196,35 +220,22 @@
|
|||
%% Plugins
|
||||
%%-------------------------------------------------------------------
|
||||
|
||||
%% Plugins Dir
|
||||
{plugins_dir, "./plugins"}.
|
||||
|
||||
%% File to store loaded plugin names.
|
||||
{plugins_loaded_file, "./data/loaded_plugins"}.
|
||||
{plugins_loaded_file, "data/loaded_plugins"}.
|
||||
|
||||
%%-------------------------------------------------------------------
|
||||
%%--------------------------------------------------------------------
|
||||
%% Modules
|
||||
%%-------------------------------------------------------------------
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%% Client presence management module. Publish presence messages when client connected or disconnected
|
||||
%% Client presence management module. Publish presence messages when
|
||||
%% client connected or disconnected.
|
||||
{module, presence, [{qos, 0}]}.
|
||||
|
||||
%% Subscribe topics automatically when client connected
|
||||
{module, subscription, [{"$queue/clients/$c", 1}, backend]}.
|
||||
|
||||
%% [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite)
|
||||
{module, rewrite, [
|
||||
|
||||
%{topic, "x/#", [
|
||||
% {rewrite, "^x/y/(.+)$", "z/y/$1"},
|
||||
% {rewrite, "^x/(.+)$", "y/$1"}
|
||||
%]},
|
||||
|
||||
%{topic, "y/+/z/#", [
|
||||
% {rewrite, "^y/(.+)/z/(.+)$", "y/z/$2"}
|
||||
%]}
|
||||
|
||||
]}.
|
||||
{module, rewrite, [{config, "etc/rewrite.conf"}]}.
|
||||
|
||||
%%-------------------------------------------------------------------
|
||||
%% Erlang System Monitor
|
||||
|
|
|
@ -0,0 +1,14 @@
|
|||
|
||||
%%--------------------------------------------------------------------
|
||||
%% [Rewrite](https://github.com/emqtt/emqttd/wiki/Rewrite)
|
||||
%%--------------------------------------------------------------------
|
||||
|
||||
%{topic, "x/#", [
|
||||
% {rewrite, "^x/y/(.+)$", "z/y/$1"},
|
||||
% {rewrite, "^x/(.+)$", "y/$1"}
|
||||
%]}.
|
||||
|
||||
%{topic, "y/+/z/#", [
|
||||
% {rewrite, "^y/(.+)/z/(.+)$", "y/z/$2"}
|
||||
%]}.
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
%% -*- mode: erlang;erlang-indent-level: 4;indent-tabs-mode: nil -*-
|
||||
%% ex: ft=erlang ts=4 sw=4 et
|
||||
|
||||
%% Platform-specific installation paths
|
||||
{platform_bin_dir, "./bin"}.
|
||||
{platform_data_dir, "./data"}.
|
||||
{platform_etc_dir, "./etc"}.
|
||||
{platform_lib_dir, "./lib"}.
|
||||
{platform_log_dir, "./log"}.
|
||||
|
||||
%%
|
||||
%% bin/emqttd
|
||||
%%
|
||||
%% {runner_script_dir, "$(cd ${0%/*} && pwd)"}.
|
||||
{runner_base_dir, "${RUNNER_SCRIPT_DIR%/*}"}.
|
||||
{runner_etc_dir, "$RUNNER_BASE_DIR/etc"}.
|
||||
{runner_log_dir, "$RUNNER_BASE_DIR/log"}.
|
||||
{pipe_dir, "/tmp/$RUNNER_SCRIPT/"}.
|
||||
{runner_user, ""}.
|
|
@ -0,0 +1,41 @@
|
|||
|
||||
{release, {emqttd, "2.0"}, [
|
||||
sasl,
|
||||
os_mon,
|
||||
runtime_tools,
|
||||
{mnesia, load},
|
||||
emqttd
|
||||
]}.
|
||||
|
||||
{include_src, false}.
|
||||
|
||||
{extended_start_script, false}.
|
||||
|
||||
{sys_config, "rel/sys.config"}.
|
||||
|
||||
{vm_args, "rel/vm.args"}.
|
||||
|
||||
{overlay_vars, "./rel/vars.config"}.
|
||||
|
||||
{overlay, [
|
||||
{mkdir, "etc/"},
|
||||
{mkdir, "etc/ssl/"},
|
||||
{mkdir, "data/"},
|
||||
{mkdir, "data/mnesia"},
|
||||
{mkdir, "log/"},
|
||||
{copy, "etc/ssl/ssl.crt", "etc/ssl/ssl.crt"},
|
||||
{copy, "etc/ssl/ssl.key", "etc/ssl/ssl.key"},
|
||||
|
||||
{template, "bin/emqttd", "bin/emqttd"},
|
||||
{template, "bin/emqttd_ctl", "bin/emqttd_ctl"},
|
||||
{copy, "bin/nodetool", "bin/nodetool"},
|
||||
{copy, "bin/nodetool", "erts-\{\{erts_vsn\}\}/bin/nodetool"},
|
||||
{copy, "bin/install_upgrade_escript", "bin/install_upgrade_escript"},
|
||||
|
||||
{template, "etc/acl.conf", "etc/acl.conf"},
|
||||
{template, "etc/client.conf", "etc/client.conf"},
|
||||
{template, "etc/emqttd.conf", "etc/emqttd.conf"},
|
||||
{template, "etc/passwd.conf", "etc/passwd.conf"},
|
||||
{template, "etc/rewrite.conf", "etc/rewrite.conf"}
|
||||
]}.
|
||||
|
|
@ -5,7 +5,7 @@
|
|||
{id, "emqttd"},
|
||||
{modules, []},
|
||||
{registered, []},
|
||||
{applications, [kernel, stdlib, gproc, esockd, mochiweb]},
|
||||
{applications, [kernel, stdlib, gproc, esockd, mochiweb, gen_logger, gen_conf]},
|
||||
{mod, {emqttd_app, []}},
|
||||
{env, []}
|
||||
]}.
|
||||
|
|
|
@ -39,7 +39,7 @@
|
|||
%% Client State
|
||||
-record(client_state, {connection, connname, peername, peerhost, peerport,
|
||||
await_recv, conn_state, rate_limit, parser_fun,
|
||||
proto_state, packet_opts, keepalive}).
|
||||
proto_state, packet_opts, keepalive, mountpoint}).
|
||||
|
||||
-define(INFO_KEYS, [peername, peerhost, peerport, await_recv, conn_state]).
|
||||
|
||||
|
|
Loading…
Reference in New Issue