diff options
Diffstat (limited to 'ejabberdctl.template')
-rwxr-xr-x | ejabberdctl.template | 472 |
1 files changed, 170 insertions, 302 deletions
diff --git a/ejabberdctl.template b/ejabberdctl.template index 5b34ebee4..a940c3df7 100755 --- a/ejabberdctl.template +++ b/ejabberdctl.template @@ -1,4 +1,4 @@ -#!/bin/bash +#!/bin/sh # define default configuration POLL=true @@ -7,138 +7,92 @@ ERL_MAX_PORTS=32000 ERL_PROCESSES=250000 ERL_MAX_ETS_TABLES=1400 FIREWALL_WINDOW="" +INET_DIST_INTERFACE="" ERLANG_NODE=ejabberd@localhost # define default environment variables -SCRIPT_DIR=`cd ${0%/*} && pwd` -ERL={{erl}} -IEX={{bindir}}/iex -EPMD={{epmd}} -INSTALLUSER={{installuser}} -ERL_LIBS={{libdir}} +SCRIPT_DIR=$(cd "${0%/*}" && pwd) +ERL="{{erl}}" +IEX="{{bindir}}/iex" +EPMD="{{epmd}}" +INSTALLUSER="{{installuser}}" -# check the proper system user is used if defined -if [ "$INSTALLUSER" != "" ] ; then - EXEC_CMD="false" - for GID in `id -G`; do - if [ $GID -eq 0 ] ; then - INSTALLUSER_HOME=$(getent passwd "$INSTALLUSER" | cut -d: -f6) - if [ -n "$INSTALLUSER_HOME" ] && [ ! -d "$INSTALLUSER_HOME" ] ; then - mkdir -p "$INSTALLUSER_HOME" - chown "$INSTALLUSER" "$INSTALLUSER_HOME" - fi - EXEC_CMD="su $INSTALLUSER -c" +# check the proper system user is used +case $(id -un) in + "$INSTALLUSER") + EXEC_CMD="as_current_user" + ;; + root) + if [ -n "$INSTALLUSER" ] ; then + EXEC_CMD="as_install_user" + else + EXEC_CMD="as_current_user" + echo "WARNING: It is not recommended to run ejabberd as root" >&2 fi - done - if [ `id -g` -eq `id -g $INSTALLUSER` ] ; then - EXEC_CMD="bash -c" - fi - if [ "$EXEC_CMD" = "false" ] ; then - echo "This command can only be run by root or the user $INSTALLUSER" >&2 - exit 4 - fi -else - EXEC_CMD="bash -c" -fi + ;; + *) + if [ -n "$INSTALLUSER" ] ; then + echo "ERROR: This command can only be run by root or the user $INSTALLUSER" >&2 + exit 7 + else + EXEC_CMD="as_current_user" + fi + ;; +esac # parse command line parameters -declare -a ARGS=() -while [ $# -ne 0 ] ; do - PARAM="$1" - shift - case $PARAM in - --) break ;; - --no-timeout) EJABBERD_NO_TIMEOUT="--no-timeout" ;; - --node) ERLANG_NODE_ARG=$1 ; shift ;; - --config-dir) ETC_DIR="$1" ; shift ;; - --config) EJABBERD_CONFIG_PATH="$1" ; shift ;; - --ctl-config) EJABBERDCTL_CONFIG_PATH="$1" ; shift ;; - --logs) LOGS_DIR="$1" ; shift ;; - --spool) SPOOL_DIR="$1" ; shift ;; - *) ARGS=("${ARGS[@]}" "$PARAM") ;; +while [ $# -gt 0 ]; do + case $1 in + -n|--node) ERLANG_NODE_ARG=$2; shift 2;; + -s|--spool) SPOOL_DIR=$2; shift 2;; + -l|--logs) LOGS_DIR=$2; shift 2;; + -f|--config) EJABBERD_CONFIG_PATH=$2; shift 2;; + -c|--ctl-config) EJABBERDCTL_CONFIG_PATH=$2; shift 2;; + -d|--config-dir) ETC_DIR=$2; shift 2;; + -t|--no-timeout) NO_TIMEOUT="--no-timeout"; shift;; + *) break;; esac done -# Define ejabberd variable if they have not been defined from the command line -if [ "$ETC_DIR" = "" ] ; then - ETC_DIR={{sysconfdir}}/ejabberd -fi -if [ "$EJABBERDCTL_CONFIG_PATH" = "" ] ; then - EJABBERDCTL_CONFIG_PATH=$ETC_DIR/ejabberdctl.cfg -fi -if [ -f "$EJABBERDCTL_CONFIG_PATH" ] ; then - . "$EJABBERDCTL_CONFIG_PATH" -fi -if [ "$EJABBERD_CONFIG_PATH" = "" ] ; then - EJABBERD_CONFIG_PATH=$ETC_DIR/ejabberd.yml -fi -if [ "$LOGS_DIR" = "" ] ; then - LOGS_DIR={{localstatedir}}/log/ejabberd -fi -if [ "$SPOOL_DIR" = "" ] ; then - SPOOL_DIR={{localstatedir}}/lib/ejabberd -fi -if [ "$EJABBERD_DOC_PATH" = "" ] ; then - EJABBERD_DOC_PATH={{docdir}} -fi -if [ "$ERLANG_NODE_ARG" != "" ] ; then - ERLANG_NODE=$ERLANG_NODE_ARG -fi -if [ "{{release}}" != "true" -a "$EJABBERD_BIN_PATH" = "" ] ; then - EJABBERD_BIN_PATH={{libdir}}/ejabberd/priv/bin -fi -EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log -DATETIME=`date "+%Y%m%d-%H%M%S"` -ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump -ERL_INETRC=$ETC_DIR/inetrc +# define ejabberd variables if not already defined from the command line +: "${ETC_DIR:="{{sysconfdir}}/ejabberd"}" +: "${LOGS_DIR:="{{localstatedir}}/log/ejabberd"}" +: "${SPOOL_DIR:="{{localstatedir}}/lib/ejabberd"}" +: "${EJABBERD_CONFIG_PATH:="$ETC_DIR/ejabberd.yml"}" +: "${EJABBERDCTL_CONFIG_PATH:="$ETC_DIR/ejabberdctl.cfg"}" +[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH" +[ -n "$ERLANG_NODE_ARG" ] && ERLANG_NODE="$ERLANG_NODE_ARG" +[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && S="-s" +: "${EJABBERD_DOC_PATH:="{{docdir}}"}" +: "${EJABBERD_LOG_PATH:="$LOGS_DIR/ejabberd.log"}" -# define mnesia options -MNESIA_OPTS="-mnesia dir \"\\\"$SPOOL_DIR\\\"\" $MNESIA_OPTIONS" # define erl parameters ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" -KERNEL_OPTS="" -if [ "$FIREWALL_WINDOW" != "" ] ; then - KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" +if [ -n "$FIREWALL_WINDOW" ] ; then + ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" fi -if [ "$INET_DIST_INTERFACE" != "" ] ; then - INET_DIST_INTERFACE2="$(echo $INET_DIST_INTERFACE | sed 's/\./,/g')" - if [ "$INET_DIST_INTERFACE" != "$INET_DIST_INTERFACE2" ] ; then - INET_DIST_INTERFACE2="{$INET_DIST_INTERFACE2}" +if [ -n "$INET_DIST_INTERFACE" ] ; then + INET_DIST_INTERFACE2=$("$ERL" -noshell -eval 'case inet:parse_address("'$INET_DIST_INTERFACE'") of {ok,IP} -> io:format("~p",[IP]); _ -> ok end.' -s erlang halt) + if [ -n "$INET_DIST_INTERFACE2" ] ; then + ERLANG_OPTS="$ERLANG_OPTS -kernel inet_dist_use_interface $INET_DIST_INTERFACE2" fi - KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE2}\"" -fi -if [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] ; then - NAME="-sname" -else - NAME="-name" -fi -IEXNAME="-$NAME" - -# define ejabberd environment parameters -if [ "$EJABBERD_CONFIG_PATH" != "${EJABBERD_CONFIG_PATH%.yml}" ] ; then - rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) - rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) - count=$(sed '/^[ ]*log_rotate_count/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) - date=$(sed '/^[ ]*log_rotate_date/!d;s/.*://;s/ *//' $EJABBERD_CONFIG_PATH) -else - rate=$(sed '/^[ ]*log_rate_limit/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) - rotate=$(sed '/^[ ]*log_rotate_size/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) - count=$(sed '/^[ ]*log_rotate_count/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) - date=$(sed '/^[ ]*log_rotate_date/!d;s/.*,//;s/ *//;s/}\.//' $EJABBERD_CONFIG_PATH) fi -[ -z "$rate" ] || EJABBERD_OPTS="log_rate_limit $rate" -[ -z "$rotate" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_size $rotate" -[ -z "$count" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_count $count" -[ -z "$date" ] || EJABBERD_OPTS="${EJABBERD_OPTS} log_rotate_date '$date'" -[ -z "$EJABBERD_OPTS" ] || EJABBERD_OPTS="-ejabberd ${EJABBERD_OPTS}" +ERL_LIBS={{libdir}} +ERL_CRASH_DUMP="$LOGS_DIR"/erl_crash_$(date "+%Y%m%d-%H%M%S").dump +ERL_INETRC="$ETC_DIR"/inetrc -[ -d "$SPOOL_DIR" ] || $EXEC_CMD "mkdir -p $SPOOL_DIR" -cd "$SPOOL_DIR" +# define ejabberd parameters +EJABBERD_OPTS="$EJABBERD_OPTS\ +$(sed '/^log_rate_limit/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\ +$(sed '/^log_rotate_size/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\ +$(sed '/^log_rotate_count/!d;s/:[ \t]*\([0-9]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")\ +$(sed '/^log_rotate_date/!d;s/:[ \t]*\(.[^ ]*\).*/ \1/;s/^/ /' "$EJABBERD_CONFIG_PATH")" +[ -n "$EJABBERD_OPTS" ] && EJABBERD_OPTS="-ejabberd $EJABBERD_OPTS" +EJABBERD_OPTS="-mnesia dir \"$SPOOL_DIR\" $MNESIA_OPTIONS $EJABBERD_OPTS -s ejabberd" # export global variables export EJABBERD_CONFIG_PATH export EJABBERD_LOG_PATH -export EJABBERD_BIN_PATH export EJABBERD_DOC_PATH export EJABBERD_PID_PATH export ERL_CRASH_DUMP @@ -150,116 +104,26 @@ export CONTRIB_MODULES_PATH export CONTRIB_MODULES_CONF_DIR export ERL_LIBS -shell_escape_str() +# run command either directly or via su $INSTALLUSER +exec_cmd() { - if test $# -eq 0; then - printf '"" ' - else - shell_escape "$@" - fi -} - -shell_escape() -{ - local RES=() - for i in "$@"; do - if test -z "$i"; then - printf '"" ' - else - printf '%q ' "$i" - fi - done -} - -# start server -start() -{ - check_start - CMD="`shell_escape \"$ERL\" \"$NAME\" \"$ERLANG_NODE\"` \ - -noinput -detached \ - $MNESIA_OPTS \ - $KERNEL_OPTS \ - $EJABBERD_OPTS \ - -s ejabberd \ - $ERLANG_OPTS \ - `shell_escape \"${ARGS[@]}\" \"$@\"`" - $EXEC_CMD "$CMD" -} - -# attach to server -debug() -{ - debugwarning - NID=$(uid debug) - CMD="`shell_escape \"$ERL\" \"$NAME\" \"$NID\"` \ - -remsh $ERLANG_NODE \ - -hidden \ - $KERNEL_OPTS \ - $ERLANG_OPTS \ - `shell_escape \"${ARGS[@]}\" \"$@\"`" - $EXEC_CMD "$CMD" -} - -# attach to server using Elixir -iexdebug() -{ - debugwarning - # Elixir shell is hidden as default - NID=$(uid debug) - CMD="`shell_escape \"$IEX\" \"$IEXNAME\" \"$NID\"` \ - -remsh $ERLANG_NODE \ - --erl `shell_escape \"$KERNEL_OPTS\"` \ - --erl `shell_escape \"$ERLANG_OPTS\"` \ - --erl `shell_escape \"${ARGS[@]}\"` \ - --erl `shell_escape_str \"$@\"`" - $EXEC_CMD "ERL_PATH=\"$ERL\" $CMD" -} - -# start interactive server -live() -{ - livewarning - CMD="`shell_escape \"$ERL\" \"$NAME\" \"${ERLANG_NODE}\"` \ - $MNESIA_OPTS \ - $KERNEL_OPTS \ - $EJABBERD_OPTS \ - -s ejabberd \ - $ERLANG_OPTS \ - `shell_escape \"${ARGS[@]}\" \"$@\"`" - $EXEC_CMD "$CMD" + case $EXEC_CMD in + as_install_user) su -s /bin/sh -c '"$0" "$@"' "$INSTALLUSER" -- "$@" ;; + as_current_user) "$@" ;; + esac } - -# start interactive server with Elixir -iexlive() +exec_erl() { - livewarning - echo $@ - CMD="`shell_escape \"$IEX\" \"$IEXNAME\" \"${ERLANG_NODE}\"` \ - --erl \"-mnesia dir \\\"$SPOOL_DIR\\\"\" \ - --erl \"`shell_escape \"$KERNEL_OPTS\"`\" \ - --erl \"`shell_escape \"$EJABBERD_OPTS\"`\" \ - --app ejabberd \ - --erl `shell_escape \"$ERLANG_OPTS\"` \ - --erl `shell_escape \"${ARGS[@]}\"` \ - --erl `shell_escape_str \"$@\"`" - $EXEC_CMD "ERL_PATH=\"$ERL\" $CMD" + NODE=$1; shift + exec_cmd "$ERL" ${S:--}name "$NODE" $ERLANG_OPTS "$@" } - -# start server in the foreground -foreground() +exec_iex() { - check_start - CMD="`shell_escape \"$ERL\" \"$NAME\" \"$ERLANG_NODE\"` \ - -noinput \ - $MNESIA_OPTS \ - $KERNEL_OPTS \ - $EJABBERD_OPTS \ - -s ejabberd \ - $ERLANG_OPTS \ - `shell_escape \"${ARGS[@]}\" \"$@\"`" - $EXEC_CMD "$CMD" + NODE=$1; shift + exec_cmd "$IEX" -${S:--}name "$NODE" --erl "$ERLANG_OPTS" "$@" } +# usage debugwarning() { if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then @@ -279,14 +143,13 @@ debugwarning() echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo " EJABBERD_BYPASS_WARNINGS=true" echo "Press return to continue" - read foo + read -r input echo "" fi } livewarning() { - check_start if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then echo "--------------------------------------------------------------------" echo "" @@ -303,37 +166,11 @@ livewarning() echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" echo " EJABBERD_BYPASS_WARNINGS=true" echo "Press return to continue" - read foo + read -r input echo "" fi } -etop() -{ - NID=$(uid top) - $EXEC_CMD "$ERL \ - $NAME $NID \ - -hidden -s etop -s erlang halt -output text -node $ERLANG_NODE" -} - -ping() -{ - [ -z "$1" ] && PEER=${ERLANG_NODE} || PEER=$1 - if [ "$PEER" = "${PEER%.*}" ] ; then - PING_NAME="-sname" - PING_NODE=$(hostname -s) - else - PING_NAME="-name" - PING_NODE=$(hostname) - fi - NID=$(uid ping ${PING_NODE}) - $EXEC_CMD "$ERL \ - $PING_NAME $NID \ - -hidden $KERNEL_OPTS $ERLANG_OPTS \ - -eval 'io:format(\"~p~n\",[net_adm:ping('\"'\"'$PEER'\"'\"')])' \ - -s erlang halt -output text -noinput" -} - help() { echo "" @@ -355,33 +192,16 @@ help() echo "" } -# common control function -ctl() -{ - NID=$(uid ctl) - CMD="`shell_escape \"$ERL\" \"$NAME\" \"$NID\"` \ - -noinput -hidden $KERNEL_OPTS -s ejabberd_ctl \ - -extra `shell_escape \"$ERLANG_NODE\"` $EJABBERD_NO_TIMEOUT \ - `shell_escape \"$@\"`" - $EXEC_CMD "$CMD" - result=$? - case $result in - 2) help;; - 3) help;; - *) :;; - esac - return $result -} - +# dynamic node name helper uid() { uuid=$(uuidgen 2>/dev/null) - [ -z "$uuid" -a -f /proc/sys/kernel/random/uuid ] && uuid=$(</proc/sys/kernel/random/uuid) - [ -z "$uuid" ] && uuid=$(printf "%X" $RANDOM$(date +%M%S)$$) + [ -z "$uuid" ] && [ -f /proc/sys/kernel/random/uuid ] && uuid=$(cat /proc/sys/kernel/random/uuid) + [ -z "$uuid" ] && uuid=$(printf "%X" "${RANDOM:-$$}$(date +%M%S)") uuid=${uuid%%-*} - [ $# -eq 0 ] && echo ${uuid}-${ERLANG_NODE} - [ $# -eq 1 ] && echo ${uuid}-${1}-${ERLANG_NODE} - [ $# -eq 2 ] && echo ${uuid}-${1}@${2} + [ $# -eq 0 ] && echo "${uuid}-${ERLANG_NODE}" + [ $# -eq 1 ] && echo "${uuid}-${1}-${ERLANG_NODE}" + [ $# -eq 2 ] && echo "${uuid}-${1}@${2}" } # stop epmd if there is no other running node @@ -391,56 +211,104 @@ stop_epmd() } # make sure node not already running and node name unregistered +# if all ok, ensure runtime directory exists and make it current directory check_start() { "$EPMD" -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && { - ps ux | grep -v grep | grep -q " $ERLANG_NODE " && { + pgrep -f "$ERLANG_NODE" >/dev/null && { echo "ERROR: The ejabberd node '$ERLANG_NODE' is already running." exit 4 - } || { - ps ux | grep -v grep | grep -q beam && { - echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered," - echo " but no related beam process has been found." - echo "Shutdown all other erlang nodes, and call 'epmd -kill'." - exit 5 - } || { - "$EPMD" -kill >/dev/null - } } + pgrep beam >/dev/null && { + echo "ERROR: The ejabberd node '$ERLANG_NODE' is registered," + echo " but no related beam process has been found." + echo "Shutdown all other erlang nodes, and call 'epmd -kill'." + exit 5 + } + "$EPMD" -kill >/dev/null } } # allow sync calls -wait_for_status() +wait_status() { # args: status try delay # return: 0 OK, 1 KO - timeout=$2 + timeout="$2" status=4 - while [ $status -ne $1 ] ; do - sleep $3 - timeout=`expr $timeout - 1` - [ $timeout -eq 0 ] && { - status=$1 - } || { - ctl status > /dev/null - status=$? - } + while [ "$status" -ne "$1" ] ; do + sleep "$3" + timeout=$((timeout - 1)) + if [ $timeout -eq 0 ] ; then + status="$1" + else + exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \ + -extra "$ERLANG_NODE" $NO_TIMEOUT status > /dev/null + status="$?" + fi done - [ $timeout -eq 0 ] && return 1 || return 0 + [ $timeout -gt 0 ] +} + +# ensure we can change current directory to SPOOL_DIR +[ -d "$SPOOL_DIR" ] || exec_cmd mkdir -p "$SPOOL_DIR" +cd "$SPOOL_DIR" || { + echo "ERROR: can not access directory $SPOOL_DIR" + exit 6 } -# main handler -case "${ARGS[0]}" in - 'start') start;; - 'debug') debug;; - 'iexdebug') iexdebug;; - 'live') live;; - 'iexlive') iexlive;; - 'foreground') foreground;; - 'ping'*) ping ${ARGS[1]};; - 'etop') etop;; - 'started') wait_for_status 0 30 2;; # wait 30x2s before timeout - 'stopped') wait_for_status 3 30 2 && stop_epmd;; # wait 30x2s before timeout - *) ctl "${ARGS[@]}";; +# main +case $1 in + start) + check_start + exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -detached + ;; + foreground) + check_start + exec_erl "$ERLANG_NODE" $EJABBERD_OPTS -noinput + ;; + live) + livewarning + check_start + exec_erl "$ERLANG_NODE" $EJABBERD_OPTS + ;; + debug) + debugwarning + exec_erl "$(uid debug)" -hidden -remsh "$ERLANG_NODE" + ;; + etop) + exec_erl "$(uid top)" -hidden -node "$ERLANG_NODE" -s etop \ + -s erlang halt -output text + ;; + iexdebug) + debugwarning + exec_iex "$(uid debug)" --remsh "$ERLANG_NODE" + ;; + iexlive) + livewarning + exec_iex "$ERLANG_NODE" --erl "$EJABBERD_OPTS" --app ejabberd + ;; + ping) + PEER=${2:-$ERLANG_NODE} + [ "$PEER" = "${PEER%.*}" ] && PS="-s" + exec_cmd "$ERL" ${PS:--}name "$(uid ping "$(hostname $PS)")" $ERLANG_OPTS \ + -noinput -hidden -eval 'io:format("~p~n",[net_adm:ping('"'$PEER'"')])' \ + -s erlang halt -output text + ;; + started) + wait_status 0 30 2 # wait 30x2s before timeout + ;; + stopped) + wait_status 3 30 2 && stop_epmd # wait 30x2s before timeout + ;; + *) + exec_erl "$(uid ctl)" -hidden -noinput -s ejabberd_ctl \ + -extra "$ERLANG_NODE" $NO_TIMEOUT "$@" + result=$? + case $result in + 2|3) help;; + *) :;; + esac + exit $result + ;; esac |