25
1
mirror of https://github.com/processone/ejabberd.git synced 2024-11-24 16:23:40 +01:00

improve ejabberdctl, and support different node names (thanks to Zach Calvert)(EJAB-1611)

This commit is contained in:
Christophe Romain 2013-06-18 15:56:28 +02:00
parent 1ea5614209
commit 55fb85107e
2 changed files with 151 additions and 149 deletions

View File

@ -55,11 +55,10 @@
# #
# This communication is used by ejabberdctl command line tool, # This communication is used by ejabberdctl command line tool,
# and in a cluster of several ejabberd nodes. # and in a cluster of several ejabberd nodes.
# Notice that the IP address must be specified in the Erlang syntax.
# #
# Default: {127,0,0,1} # Default: 127.0.0.1
# #
INET_DIST_INTERFACE={127,0,0,1} #INET_DIST_INTERFACE=127.0.0.1
#. #.
#' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections #' ERL_EPMD_ADDRESS: IP addresses where epmd listens for connections

View File

@ -6,24 +6,45 @@ SMP=auto
ERL_MAX_PORTS=32000 ERL_MAX_PORTS=32000
ERL_PROCESSES=250000 ERL_PROCESSES=250000
ERL_MAX_ETS_TABLES=1400 ERL_MAX_ETS_TABLES=1400
FIREWALL_WINDOW=""
SCRIPT_DIR=$(cd ${0%/*} && pwd) INET_DIST_INTERFACE="127.0.0.1"
ERLANG_NODE=ejabberd@localhost
# define default environment variables # define default environment variables
NODE=ejabberd SCRIPT_DIR=`cd ${0%/*} && pwd`
HOST=localhost
ERLANG_NODE=$NODE@$HOST
ERL={{erl}} ERL={{erl}}
INSTALLUSER={{installuser}} INSTALLUSER={{installuser}}
# Compatibility in ZSH
#setopt shwordsplit 2>/dev/null
# 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
EXEC_CMD="su $INSTALLUSER -p -c"
fi
done
if [ `id -g` -eq `id -g $INSTALLUSER` ] ; 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
else
EXEC_CMD="sh -c"
fi
# parse command line parameters # parse command line parameters
ARGS= ARGS=""
while [ $# -ne 0 ] ; do while [ $# -ne 0 ] ; do
PARAM=$1 PARAM=$1
shift shift
case $PARAM in case $PARAM in
--) break ;; --) break ;;
--node) ERLANG_NODE_ARG=$1; shift ;; --node) ERLANG_NODE_ARG=$1 ; shift ;;
--config-dir) ETCDIR=$1 ; shift ;; --config-dir) ETCDIR=$1 ; shift ;;
--config) EJABBERD_CONFIG_PATH=$1 ; shift ;; --config) EJABBERD_CONFIG_PATH=$1 ; shift ;;
--ctl-config) EJABBERDCTL_CONFIG_PATH=$1 ; shift ;; --ctl-config) EJABBERDCTL_CONFIG_PATH=$1 ; shift ;;
@ -37,13 +58,15 @@ done
if [ "$ETCDIR" = "" ] ; then if [ "$ETCDIR" = "" ] ; then
ETCDIR={{sysconfdir}}/ejabberd ETCDIR={{sysconfdir}}/ejabberd
fi fi
if [ "$EJABBERD_CONFIG_PATH" = "" ] ; then
EJABBERD_CONFIG_PATH=$ETCDIR/ejabberd.cfg
fi
if [ "$EJABBERDCTL_CONFIG_PATH" = "" ] ; then if [ "$EJABBERDCTL_CONFIG_PATH" = "" ] ; then
EJABBERDCTL_CONFIG_PATH=$ETCDIR/ejabberdctl.cfg EJABBERDCTL_CONFIG_PATH=$ETCDIR/ejabberdctl.cfg
fi fi
[ -f "$EJABBERDCTL_CONFIG_PATH" ] && . "$EJABBERDCTL_CONFIG_PATH" if [ -f "$EJABBERDCTL_CONFIG_PATH" ] ; then
. "$EJABBERDCTL_CONFIG_PATH"
fi
if [ "$EJABBERD_CONFIG_PATH" = "" ] ; then
EJABBERD_CONFIG_PATH=$ETCDIR/ejabberd.cfg
fi
if [ "$LOGS_DIR" = "" ] ; then if [ "$LOGS_DIR" = "" ] ; then
LOGS_DIR={{localstatedir}}/log/ejabberd LOGS_DIR={{localstatedir}}/log/ejabberd
fi fi
@ -57,39 +80,6 @@ if [ "$ERLANG_NODE_ARG" != "" ] ; then
ERLANG_NODE=$ERLANG_NODE_ARG ERLANG_NODE=$ERLANG_NODE_ARG
NODE=${ERLANG_NODE%@*} NODE=${ERLANG_NODE%@*}
fi 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 [ "{{release}}" != "true" ] ; then
if [ "$EJABBERDDIR" = "" ] ; then if [ "$EJABBERDDIR" = "" ] ; then
EJABBERDDIR={{libdir}}/ejabberd EJABBERDDIR={{libdir}}/ejabberd
@ -110,7 +100,6 @@ if [ "{{release}}" != "true" ] ; then
EJABBERD_MSGS_PATH=$EJABBERD_PRIV_PATH/msgs EJABBERD_MSGS_PATH=$EJABBERD_PRIV_PATH/msgs
fi fi
fi fi
EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log EJABBERD_LOG_PATH=$LOGS_DIR/ejabberd.log
SASL_LOG_PATH=$LOGS_DIR/erlang.log SASL_LOG_PATH=$LOGS_DIR/erlang.log
DATETIME=`date "+%Y%m%d-%H%M%S"` DATETIME=`date "+%Y%m%d-%H%M%S"`
@ -118,11 +107,25 @@ ERL_CRASH_DUMP=$LOGS_DIR/erl_crash_$DATETIME.dump
ERL_INETRC=$ETCDIR/inetrc ERL_INETRC=$ETCDIR/inetrc
HOME=$SPOOLDIR HOME=$SPOOLDIR
# create the home dir with the proper user if doesn't exist, because it stores cookie file # define erl parameters
[ -d $HOME ] || $EXEC_CMD "mkdir -p $HOME" 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#*-}"
fi
if [ "$INET_DIST_INTERFACE" != "" ] ; then
KERNEL_OPTS="${KERNEL_OPTS} -kernel inet_dist_use_interface \"{${INET_DIST_INTERFACE//./,}}\""
fi
if [ "$ERLANG_NODE" = "${ERLANG_NODE%.*}" ] ; then
NAME="-sname"
else
NAME="-name"
fi
# Change to a directory readable by INSTALLUSER to # create the ejabberd home dir with the proper user if doesn't exist
# then change to that directory readable by INSTALLUSER to
# prevent "File operation error: eacces." messages # prevent "File operation error: eacces." messages
[ -d $HOME ] || $EXEC_CMD "mkdir -p $HOME"
cd $HOME cd $HOME
# export global variables # export global variables
@ -141,16 +144,10 @@ export ERL_MAX_ETS_TABLES
export HOME export HOME
export EXEC_CMD export EXEC_CMD
# Compatibility in ZSH
#setopt shwordsplit 2>/dev/null
# start server # start server
start () start()
{ {
checknodenameusage check_start
[ "$?" -eq 0 ] && echo "\nERROR: The node '$ERLANG_NODE' is already running." && return 1
$EXEC_CMD "$ERL \ $EXEC_CMD "$ERL \
$NAME $ERLANG_NODE \ $NAME $ERLANG_NODE \
-noinput -detached \ -noinput -detached \
@ -163,7 +160,7 @@ start ()
} }
# attach to server # attach to server
debug () debug()
{ {
echo "--------------------------------------------------------------------" echo "--------------------------------------------------------------------"
echo "" echo ""
@ -195,11 +192,9 @@ debug ()
} }
# start interactive server # start interactive server
live () live()
{ {
checknodenameusage check_start
[ "$?" -eq 0 ] && echo "\nERROR: The node '$ERLANG_NODE' is already running." && return 1
echo "--------------------------------------------------------------------" echo "--------------------------------------------------------------------"
echo "" echo ""
echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode." echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode."
@ -228,7 +223,14 @@ live ()
$ERLANG_OPTS $ARGS \"$@\"" $ERLANG_OPTS $ARGS \"$@\""
} }
help () etop()
{
$EXEC_CMD "$ERL \
$NAME debug-${TTY}-${ERLANG_NODE} \
-hidden -s etop -s erlang halt -output text -node $ERLANG_NODE"
}
help()
{ {
echo "" echo ""
echo "Commands to start an ejabberd node:" echo "Commands to start an ejabberd node:"
@ -247,7 +249,7 @@ help ()
} }
# common control function # common control function
ctl () ctl()
{ {
COMMAND=$@ COMMAND=$@
@ -277,7 +279,7 @@ ctl ()
# conn names -- this allows # conn names -- this allows
# concurrent invocations using a bound # concurrent invocations using a bound
# number of atoms # number of atoms
for N in $(seq 1 $MAXCONNID); do for N in `seq 1 $MAXCONNID`; do
CTL_CONN="ejabberdctl-$N" CTL_CONN="ejabberdctl-$N"
CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN" CTL_LOCKFILE="$CONNLOCKDIR/$CTL_CONN"
( (
@ -286,14 +288,14 @@ ctl ()
ctlexec $CTL_CONN $COMMAND ctlexec $CTL_CONN $COMMAND
ssresult=$? ssresult=$?
# segregate from possible flock exit(1) # segregate from possible flock exit(1)
ssresult=$(expr $ssresult \* 10) ssresult=`expr $ssresult \* 10`
exit $ssresult exit $ssresult
else else
exit 1 exit 1
fi fi
) )
result=$? result=$?
if [ $result -eq 1 ]; then if [ $result -eq 1 ] ; then
# means we errored out in flock # means we errored out in flock
# rather than in the exec - stay in the loop # rather than in the exec - stay in the loop
# trying other conn names... # trying other conn names...
@ -303,10 +305,10 @@ ctl ()
break; break;
fi fi
done done
result=$(expr $result / 10) result=`expr $result / 10`
fi fi
if [ "$badlock" ];then if [ "$badlock" ] ;then
echo "Ran out of connections to try. Your ejabberd processes" >&2 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 "may be stuck or this is a very busy server. For very" >&2
echo "busy servers, consider raising MAXCONNID in ejabberdctl">&2 echo "busy servers, consider raising MAXCONNID in ejabberdctl">&2
@ -322,7 +324,7 @@ ctl ()
return $result return $result
} }
ctlexec () ctlexec()
{ {
CONN_NAME=$1; shift CONN_NAME=$1; shift
COMMAND=$@ COMMAND=$@
@ -335,17 +337,30 @@ ctlexec ()
-s ejabberd_ctl -extra $ERLANG_NODE $COMMAND" -s ejabberd_ctl -extra $ERLANG_NODE $COMMAND"
} }
# display ctl usage
usage ()
{
ctl
exit
}
# stop epmd if there is no other running node # stop epmd if there is no other running node
stop_epmd() stop_epmd()
{ {
epmd -names | grep -q name || epmd -kill epmd -names 2>/dev/null | grep -q name || epmd -kill >/dev/null
}
# make sure node not already running and node name unregistered
check_start()
{
epmd -names 2>/dev/null | grep -q " ${ERLANG_NODE%@*} " && {
ps ux | grep -v grep | grep -q " $ERLANG_NODE " && {
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
}
}
}
} }
# allow sync calls # allow sync calls
@ -355,9 +370,9 @@ wait_for_status()
# return: 0 OK, 1 KO # return: 0 OK, 1 KO
timeout=$2 timeout=$2
status=4 status=4
while [ $status -ne $1 ]; do while [ $status -ne $1 ] ; do
sleep $3 sleep $3
timeout=$(($timeout - 1)) timeout=`expr $timeout - 1`
[ $timeout -eq 0 ] && { [ $timeout -eq 0 ] && {
status=$1 status=$1
} || { } || {
@ -365,28 +380,16 @@ wait_for_status()
status=$? status=$?
} }
done done
[ $timeout -eq 0 ] && { [ $timeout -eq 0 ] && return 1 || return 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 "
} }
# main handler
case $ARGS in case $ARGS in
' start') start;; ' start') start;;
' debug') debug;; ' debug') debug;;
' live') live;; ' live') live;;
' etop') etop;;
' started') wait_for_status 0 30 2;; # wait 30x2s before timeout ' started') wait_for_status 0 30 2;; # wait 30x2s before timeout
' stopped') wait_for_status 3 15 2; stop_epmd;; # wait 15x2s before timeout ' stopped') wait_for_status 3 15 2 && stop_epmd;; # wait 15x2s before timeout
*) ctl $ARGS;; *) ctl $ARGS;;
esac esac