diff options
author | Evgeniy Khramtsov <ekhramtsov@process-one.net> | 2013-04-08 11:12:54 +0200 |
---|---|---|
committer | Christophe Romain <christophe.romain@process-one.net> | 2013-06-13 11:11:02 +0200 |
commit | 4d8f7706240a1603468968f47fc7b150b788d62f (patch) | |
tree | 92d55d789cc7ac979b3c9e161ffb7f908eba043a /ejabberdctl.template | |
parent | Fix Guide: ejabberd_service expects a shaper_rule, not a shaper (diff) |
Switch to rebar build tool
Use dynamic Rebar configuration
Make iconv dependency optional
Disable transient_supervisors compile option
Add hipe compilation support
Only compile ibrowse and lhttpc when needed
Make it possible to generate an OTP application release
Add --enable-debug compile option
Add --enable-all compiler option
Add --enable-tools configure option
Add --with-erlang configure option.
Add --enable-erlang-version-check configure option.
Add lager support
Improve the test suite
Diffstat (limited to 'ejabberdctl.template')
-rwxr-xr-x | ejabberdctl.template | 392 |
1 files changed, 392 insertions, 0 deletions
diff --git a/ejabberdctl.template b/ejabberdctl.template new file mode 100755 index 000000000..a98e73ef2 --- /dev/null +++ b/ejabberdctl.template @@ -0,0 +1,392 @@ +#!/bin/sh + +# define default configuration +POLL=true +SMP=auto +ERL_MAX_PORTS=32000 +ERL_PROCESSES=250000 +ERL_MAX_ETS_TABLES=1400 + +SCRIPT_DIR=$(cd ${0%/*} && pwd) + +# define default environment variables +NODE=ejabberd +HOST=localhost +ERLANG_NODE=$NODE@$HOST +ERL={{erl}} +INSTALLUSER={{installuser}} + +# parse command line parameters +ARGS= +while [ $# -ne 0 ] ; do + PARAM=$1 + shift + case $PARAM in + --) break ;; + --node) ERLANG_NODE_ARG=$1; shift ;; + --config-dir) ETCDIR=$1 ; shift ;; + --config) EJABBERD_CONFIG_PATH=$1 ; shift ;; + --ctl-config) EJABBERDCTL_CONFIG_PATH=$1 ; shift ;; + --logs) LOGS_DIR=$1 ; shift ;; + --spool) SPOOLDIR=$1 ; shift ;; + *) ARGS="$ARGS $PARAM" ;; + esac +done + +# Define ejabberd variable if they have not been defined from the command line +if [ "$ETCDIR" = "" ] ; then + ETCDIR={{sysconfdir}}/ejabberd +fi +if [ "$EJABBERD_CONFIG_PATH" = "" ] ; then + EJABBERD_CONFIG_PATH=$ETCDIR/ejabberd.cfg +fi +if [ "$EJABBERDCTL_CONFIG_PATH" = "" ] ; then + EJABBERDCTL_CONFIG_PATH=$ETCDIR/ejabberdctl.cfg +fi +[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH" +if [ "$LOGS_DIR" = "" ] ; then + LOGS_DIR={{localstatedir}}/log/ejabberd +fi +if [ "$SPOOLDIR" = "" ] ; then + SPOOLDIR={{localstatedir}}/lib/ejabberd +fi +if [ "$EJABBERD_DOC_PATH" = "" ] ; then + EJABBERD_DOC_PATH={{docdir}} +fi +if [ "$ERLANG_NODE_ARG" != "" ] ; then + ERLANG_NODE=$ERLANG_NODE_ARG + NODE=${ERLANG_NODE%@*} +fi + +# check the proper system user is used +ID=`id -g` +GIDS=`id -G` +EJID=`id -g $INSTALLUSER` +EXEC_CMD="false" +for GID in $GIDS; do + if [ $GID -eq 0 ] ; then + EXEC_CMD="su ${INSTALLUSER} -p -c" + fi +done +if [ "$ID" -eq "$EJID" ] ; then + EXEC_CMD="sh -c" +fi +if [ "$EXEC_CMD" = "false" ] ; then + echo "This command can only be run by root or the user $INSTALLUSER" >&2 + exit 4 +fi + +NAME=-name +[ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] && NAME=-sname + +KERNEL_OPTS="" +if [ "$FIREWALL_WINDOW" != "" ] ; then + KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_listen_min ${FIREWALL_WINDOW%-*} inet_dist_listen_max ${FIREWALL_WINDOW#*-}" +fi +if [ "$INET_DIST_INTERFACE" != "" ] ; then + KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"${INET_DIST_INTERFACE}\"" +fi + +ERLANG_OPTS="+K $POLL -smp $SMP +P $ERL_PROCESSES $ERL_OPTIONS" + +# define additional environment variables +if [ "{{release}}" != "true" ] ; then + if [ "$EJABBERDDIR" = "" ] ; then + EJABBERDDIR={{libdir}}/ejabberd + fi + if [ "$EJABBERD_EBIN_PATH" = "" ] ; then + EJABBERD_EBIN_PATH=$EJABBERDDIR/ebin + fi + if [ "$EJABBERD_PRIV_PATH" = "" ] ; then + EJABBERD_PRIV_PATH=$EJABBERDDIR/priv + fi + if [ "$EJABBERD_BIN_PATH" = "" ] ; then + EJABBERD_BIN_PATH=$EJABBERD_PRIV_PATH/bin + fi + if [ "$EJABBERD_SO_PATH" = "" ] ; then + EJABBERD_SO_PATH=$EJABBERD_PRIV_PATH/lib + fi + if [ "$EJABBERD_MSGS_PATH" = "" ] ; then + EJABBERD_MSGS_PATH=$EJABBERD_PRIV_PATH/msgs + fi +fi + +EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log +SASL_LOG_PATH=$LOGS_DIR/erlang.log +DATETIME=`date "+%Y%m%d-%H%M%S"` +ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump +ERL_INETRC=$ETCDIR/inetrc +HOME=$SPOOLDIR + +# create the home dir with the proper user if doesn't exist, because it stores cookie file +[ -d $HOME ] || $EXEC_CMD "mkdir -p $HOME" + +# Change to a directory readable by INSTALLUSER to +# prevent "File operation error: eacces." messages +cd $HOME + +# export global variables +export EJABBERD_CONFIG_PATH +export EJABBERD_MSGS_PATH +export EJABBERD_LOG_PATH +export EJABBERD_SO_PATH +export EJABBERD_BIN_PATH +export EJABBERD_DOC_PATH +export EJABBERD_PID_PATH +export ERL_CRASH_DUMP +export ERL_EPMD_ADDRESS +export ERL_INETRC +export ERL_MAX_PORTS +export ERL_MAX_ETS_TABLES +export HOME +export EXEC_CMD + + +# Compatibility in ZSH +#setopt shwordsplit 2>/dev/null + +# start server +start () +{ + checknodenameusage + [ "$?" -eq 0 ] && echo "\nERROR: The node '$ERLANG_NODE' is already running." && return 1 + + $EXEC_CMD "$ERL \ + $NAME $ERLANG_NODE \ + -noinput -detached \ + -pa $EJABBERD_EBIN_PATH \ + -mnesia dir \"\\\"$SPOOLDIR\\\"\" \ + $KERNEL_OPTS \ + -s ejabberd \ + -sasl sasl_error_logger \\{file,\\\"$SASL_LOG_PATH\\\"\\} \ + $ERLANG_OPTS $ARGS \"$@\"" +} + +# attach to server +debug () +{ + echo "--------------------------------------------------------------------" + echo "" + echo "IMPORTANT: we will attempt to attach an INTERACTIVE shell" + echo "to an already running ejabberd node." + echo "If an ERROR is printed, it means the connection was not successful." + echo "You can interact with the ejabberd node if you know how to use it." + echo "Please be extremely cautious with your actions," + echo "and exit immediately if you are not completely sure." + echo "" + echo "To detach this shell from ejabberd, press:" + echo " control+c, control+c" + echo "" + echo "--------------------------------------------------------------------" + echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" + echo " EJABBERD_BYPASS_WARNINGS=true" + echo "Press any key to continue" + if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then + read foo + fi + echo "" + TTY=`tty | sed -e 's/.*\///g'` + $EXEC_CMD "$ERL \ + $NAME debug-${TTY}-${ERLANG_NODE} \ + -remsh $ERLANG_NODE \ + -hidden \ + $KERNEL_OPTS \ + $ERLANG_OPTS $ARGS \"$@\"" +} + +# start interactive server +live () +{ + checknodenameusage + [ "$?" -eq 0 ] && echo "\nERROR: The node '$ERLANG_NODE' is already running." && return 1 + + echo "--------------------------------------------------------------------" + echo "" + echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode." + echo "All log messages will be shown in the command shell." + echo "You can interact with the ejabberd node if you know how to use it." + echo "Please be extremely cautious with your actions," + echo "and exit immediately if you are not completely sure." + echo "" + echo "To exit this LIVE mode and stop ejabberd, press:" + echo " q(). and press the Enter key" + echo "" + echo "--------------------------------------------------------------------" + echo "To bypass permanently this warning, add to ejabberdctl.cfg the line:" + echo " EJABBERD_BYPASS_WARNINGS=true" + echo "Press any key to continue" + if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then + read foo + fi + echo "" + $EXEC_CMD "$ERL \ + $NAME $ERLANG_NODE \ + -pa $EJABBERD_EBIN_PATH \ + -mnesia dir \"\\\"$SPOOLDIR\\\"\" \ + $KERNEL_OPTS \ + -s ejabberd \ + $ERLANG_OPTS $ARGS \"$@\"" +} + +help () +{ + echo "" + echo "Commands to start an ejabberd node:" + echo " start Start an ejabberd node in server mode" + echo " debug Attach an interactive Erlang shell to a running ejabberd node" + echo " live Start an ejabberd node in live (interactive) mode" + echo "" + echo "Optional parameters when starting an ejabberd node:" + echo " --config-dir dir Config ejabberd: $ETCDIR" + echo " --config file Config ejabberd: $EJABBERD_CONFIG_PATH" + echo " --ctl-config file Config ejabberdctl: $EJABBERDCTL_CONFIG_PATH" + echo " --logs dir Directory for logs: $LOGS_DIR" + echo " --spool dir Database spool dir: $SPOOLDIR" + echo " --node nodename ejabberd node name: $ERLANG_NODE" + echo "" +} + +# common control function +ctl () +{ + COMMAND=$@ + + # Control number of connections identifiers + # using flock if available. Expects a linux-style + # flock that can lock a file descriptor. + MAXCONNID=100 + CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl + FLOCK='/usr/bin/flock' + if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then + JOT='/usr/bin/jot' + if [ ! -x "$JOT" ] ; then + # no flock or jot, simply invoke ctlexec() + CTL_CONN="ctl-${ERLANG_NODE}" + ctlexec $CTL_CONN $COMMAND + result=$? + else + # no flock, but at least there is jot + RAND=`jot -r 1 0 $MAXCONNID` + CTL_CONN="ctl-${RAND}-${ERLANG_NODE}" + ctlexec $CTL_CONN $COMMAND + result=$? + fi + else + # we have flock so we get a lock + # on one of a limited number of + # conn names -- this allows + # concurrent invocations using a bound + # number of atoms + for N in $(seq 1 $MAXCONNID); do + CTL_CONN="ejabberdctl-$N" + CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN" + ( + exec 8>"$CTL_LOCKFILE" + if flock --nb 8; then + ctlexec $CTL_CONN $COMMAND + ssresult=$? + # segregate from possible flock exit(1) + ssresult=$(expr $ssresult \* 10) + exit $ssresult + else + exit 1 + fi + ) + result=$? + if [ $result -eq 1 ]; then + # means we errored out in flock + # rather than in the exec - stay in the loop + # trying other conn names... + badlock=1 + else + badlock="" + break; + fi + done + result=$(expr $result / 10) + fi + + if [ "$badlock" ];then + echo "Ran out of connections to try. Your ejabberd processes" >&2 + echo "may be stuck or this is a very busy server. For very" >&2 + echo "busy servers, consider raising MAXCONNID in ejabberdctl">&2 + exit 1; + fi + + case $result in + 0) :;; + 1) :;; + 2) help;; + 3) help;; + esac + return $result +} + +ctlexec () +{ + CONN_NAME=$1; shift + COMMAND=$@ + $EXEC_CMD "$ERL \ + $NAME ${CONN_NAME} \ + -noinput \ + -hidden \ + -pa $EJABBERD_EBIN_PATH \ + $KERNEL_OPTS \ + -s ejabberd_ctl -extra $ERLANG_NODE $COMMAND" +} + +# display ctl usage +usage () +{ + ctl + exit +} + +# stop epmd if there is no other running node +stop_epmd() +{ + epmd -names | grep -q name || epmd -kill +} + +# allow sync calls +wait_for_status() +{ + # args: status try delay + # return: 0 OK, 1 KO + timeout=$2 + status=4 + while [ $status -ne $1 ]; do + sleep $3 + timeout=$(($timeout - 1)) + [ $timeout -eq 0 ] && { + status=$1 + } || { + ctl status > /dev/null + status=$? + } + done + [ $timeout -eq 0 ] && { + status=1 + } || { + status=0 + } + return $status +} + +# check node name is used or not +# $? --> 0=alreadyused 1=available +checknodenameusage () +{ + $EXEC_CMD "$ERL \ + $NAME $ERLANG_NODE \ + -s erlang halt | grep -c duplicate_name > /dev/null " +} + +case $ARGS in + ' start') start;; + ' debug') debug;; + ' live') live;; + ' started') wait_for_status 0 30 2;; # wait 30x2s before timeout + ' stopped') wait_for_status 3 15 2; stop_epmd;; # wait 15x2s before timeout + *) ctl $ARGS;; +esac |