Skip to content

Instantly share code, notes, and snippets.

@Licenser
Created August 3, 2017 21:39
Show Gist options
  • Save Licenser/31d4587900fd37d65f132e8d0b9d2fd3 to your computer and use it in GitHub Desktop.
Save Licenser/31d4587900fd37d65f132e8d0b9d2fd3 to your computer and use it in GitHub Desktop.
#!/bin/sh
set -e
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="dalmatinerpx"
CUTTLEFISH_CONF="dalmatinerpx.conf"
REL_VSN="0.3.2p5"
ERTS_VSN="8.3"
CODE_LOADING_MODE="${CODE_LOADING_MODE:-embedded}"
REL_DIR="$RELEASE_ROOT_DIR/releases/$REL_VSN"
ERL_OPTS=""
RUNNER_LOG_DIR="${RUNNER_LOG_DIR:-/data/dalmatinerpx/log }"
RUNNER_BASE_DIR=$RELEASE_ROOT_DIR
RUNNER_ETC_DIR="${RUNNER_ETC_DIR:-/data/dalmatinerpx/etc}"
RUNNER_DB_DIR="${RUNNER_ETC_DIR:-/data/dalmatinerpx/db}"
if [ "$RUNNER_ETC_DIR" = "${RUNNER_ETC_DIR#/}" ]
then
# if relative, make it relative to RELEASE_ROOT_DIR
RUNNER_ETC_DIR=$RELEASE_ROOT_DIR/$RUNNER_ETC_DIR
fi # else absolute, keep it as it is
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_longname() {
id="longname$(relx_gen_id)-${NAME}"
"$BINDIR/erl" -boot start_clean -eval 'io:format("~s~n", [node()]), halt()' -noshell -name $id | sed -e 's/.*@//g'
}
# 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 -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"
}
if [ $RELX_REPLACE_OS_VARS ]; then
awk '{while(match($0,"[$]{[^}]*}")) {var=substr($0,RSTART+2,RLENGTH -3);gsub("[$]{"var"}",ENVIRON[var])}}1' < "$RUNNER_ETC_DIR/$CUTTLEFISH_CONF" > "$RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new"
else
cp "$RUNNER_ETC_DIR/$CUTTLEFISH_CONF" "$RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new"
fi
# Make sure log directory exists
mkdir -p "$RUNNER_LOG_DIR"
# Use $CWD/sys.config if exists, otherwise releases/VSN/sys.config
if [ -z "$NAME_ARG" ]; then
NODENAME=`egrep '^[ \t]*nodename[ \t]*=[ \t]*' $RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new 2> /dev/null | tail -n 1 | cut -d = -f 2`
if [ -z "$NODENAME" ]; then
echo "vm.args needs to have a -name parameter."
echo " -sname is not supported."
echo " couldn't find 'nodename' in $RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new"
echo " \$PWD is $PWD"
exit 1
else
NAME_TYPE="-name"
NAME="${NODENAME# *}"
fi
fi
PIPE_DIR="${PIPE_DIR:-/tmp/erl_pipes/$NAME/}"
# Extract the target cookie
#COOKIE_ARG=`grep -e '-setcookie' $RUNNER_ETC_DIR/vm.args`
if [ -z "$COOKIE_ARG" ]; then
COOKIE=`egrep '^[ \t]*distributed_cookie[ \t]*=[ \t]*' $RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new 2> /dev/null | cut -d = -f 2 | tr -d ' '`
if [ -z "$COOKIE" ]; then
echo "vm.args needs to have a -setcookie parameter."
echo " couldn't find 'distributed_cookie' in $RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new"
echo " \$PWD is $PWD"
exit 1
else
COOKIE_ARG="-setcookie $COOKIE"
fi
fi
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"
CUTTLEFISHCMD="$ERTS_DIR/bin/escript $RUNNER_BASE_DIR/bin/cuttlefish"
cd "$ROOTDIR"
if CUTTLEFISH_CONFIG=$($CUTTLEFISHCMD -e $RUNNER_ETC_DIR -d ${RUNNER_DB_DIR}/generated.conf -s $RUNNER_BASE_DIR/share/schema/ -c $RUNNER_ETC_DIR/$CUTTLEFISH_CONF.new)
then
CONFIG_FILES="$CUTTLEFISH_CONFIG"
else
echo "Cuttlefish failed! Oh no!"
exit 1
fi
# 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
;;
*)
# Add @hostname
case $NAME_TYPE in
-sname)
NAME=$NAME@`hostname -s`
;;
-name)
NAME=$NAME@$(relx_get_longname)
;;
esac
;;
esac
# Check the first argument for instructions
case "$1" in
start|start_boot)
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)
# Wait for the node to completely stop...
PID="$(relx_get_pid)"
if ! relx_nodetool "stop"; then
exit 1
fi
while $(kill -s 0 "$PID" 2>/dev/null);
do
sleep 1
done
;;
restart)
## Restart the VM without exiting the process
if ! relx_nodetool "restart"; then
exit 1
fi
;;
reboot)
## Restart the VM completely (uses heart to restart it)
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
if ! relx_nodetool "ping"; then
exit 1
fi
;;
config)
shift
case "$1" in
effective) ## Great, pass through!
;;
describe)
if [ $# -lt 2 ] || [ "$2" = "-l" ]; then
echo "$RUNNER_SCRIPT config describe requires a variable name to query"
echo " Try \`$RUNNER_SCRIPT config describe setting.name\`"
exit 1
fi
;;
generate) ## Great, pass through!
;;
*)
echo "Valid commands for$RUNNER_SCRIPT config are:"
echo " $RUNNER_SCRIPT config effective"
echo " $RUNNER_SCRIPT config describe VARIABLE"
exit 1
;;
esac
CUTTLEFISH_COMMAND_PREFIX="$RUNNER_BASE_DIR/bin/cuttlefish -e $RUNNER_ETC_DIR -s $RUNNER_BASE_DIR/share/schema -d $RUNNER_BASE_DIR/generated.configs -c $RUNNER_ETC_DIR/cse_spooler.conf"
printf '%s \n' "`$CUTTLEFISH_COMMAND_PREFIX $@`"
;;
escript)
## Run an escript under the node's environment
if ! relx_escript $@; then
exit 1
fi
;;
attach)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
shift
exec "$BINDIR/to_erl" "$PIPE_DIR"
;;
remote_console)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
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
EMU=beam
PROGNAME=`echo $0 | sed 's/.*\\///'`
CMD="$BINDIR/erlexec -boot $BOOTFILE -boot_var ERTS_LIB_DIR $ERTS_LIB_DIR -mode $CODE_LOADING_MODE $CONFIG_FILES -- ${1+"$@"}"
export EMU
export ROOTDIR
export BINDIR
export PROGNAME
# Dump environment info for logging purposes
echo "Exec: $CMD"
echo "Root: $ROOTDIR"
# Log the startup
logger -t "$SCRIPT[$$]" "Starting up"
# Start the VM
exec $CMD
;;
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_FILES \
-boot_var ERTS_LIB_DIR "$ERTS_LIB_DIR"
# 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
shift
relx_nodetool rpc $@
;;
rpcterms)
# Make sure a node IS running
if ! relx_nodetool "ping" > /dev/null; then
echo "Node is not running!"
exit 1
fi
shift
relx_nodetool rpcterms $@
;;
*)
echo "Usage: $REL_NAME {start|start_boot <file>|foreground|stop|restart|reboot|pid|ping|console|console_clean|console_boot <file>|attach|remote_console|upgrade|config|escript|rpc|rpcterms}"
exit 1
;;
esac
exit 0
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment