Merge branch 'master' of github.com:processone/ejabberd

This commit is contained in:
Evgeniy Khramtsov 2013-06-19 10:41:33 +10:00
commit 2ec048a5ae
4 changed files with 192 additions and 165 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,60 +80,26 @@ 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
fi fi
if [ "$EJABBERD_EBIN_PATH" = "" ] ; then if [ "$EJABBERD_EBIN_PATH" = "" ] ; then
EJABBERD_EBIN_PATH=$EJABBERDDIR/ebin EJABBERD_EBIN_PATH=$EJABBERDDIR/ebin
fi fi
if [ "$EJABBERD_PRIV_PATH" = "" ] ; then if [ "$EJABBERD_PRIV_PATH" = "" ] ; then
EJABBERD_PRIV_PATH=$EJABBERDDIR/priv EJABBERD_PRIV_PATH=$EJABBERDDIR/priv
fi fi
if [ "$EJABBERD_BIN_PATH" = "" ] ; then if [ "$EJABBERD_BIN_PATH" = "" ] ; then
EJABBERD_BIN_PATH=$EJABBERD_PRIV_PATH/bin EJABBERD_BIN_PATH=$EJABBERD_PRIV_PATH/bin
fi fi
if [ "$EJABBERD_SO_PATH" = "" ] ; then if [ "$EJABBERD_SO_PATH" = "" ] ; then
EJABBERD_SO_PATH=$EJABBERD_PRIV_PATH/lib EJABBERD_SO_PATH=$EJABBERD_PRIV_PATH/lib
fi fi
if [ "$EJABBERD_MSGS_PATH" = "" ] ; then if [ "$EJABBERD_MSGS_PATH" = "" ] ; 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,29 @@ 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
INET_DIST_INTERFACE2="$(echo $INET_DIST_INTERFACE | sed 's/\./,/g')"
if [ "$INET_DIST_INTERFACE" != "$INET_DIST_INTERFACE2" ] ; then
INET_DIST_INTERFACE2="{$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
# 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 +148,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 +164,7 @@ start ()
} }
# attach to server # attach to server
debug () debug()
{ {
echo "--------------------------------------------------------------------" echo "--------------------------------------------------------------------"
echo "" echo ""
@ -182,7 +183,7 @@ debug ()
echo " EJABBERD_BYPASS_WARNINGS=true" echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press any key to continue" echo "Press any key to continue"
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
read foo read foo
fi fi
echo "" echo ""
TTY=`tty | sed -e 's/.*\///g'` TTY=`tty | sed -e 's/.*\///g'`
@ -195,11 +196,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."
@ -216,7 +215,7 @@ live ()
echo " EJABBERD_BYPASS_WARNINGS=true" echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press any key to continue" echo "Press any key to continue"
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
read foo read foo
fi fi
echo "" echo ""
$EXEC_CMD "$ERL \ $EXEC_CMD "$ERL \
@ -228,7 +227,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 +253,7 @@ help ()
} }
# common control function # common control function
ctl () ctl()
{ {
COMMAND=$@ COMMAND=$@
@ -258,71 +264,71 @@ ctl ()
CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl CONNLOCKDIR={{localstatedir}}/lock/ejabberdctl
FLOCK='/usr/bin/flock' FLOCK='/usr/bin/flock'
if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then if [ ! -x "$FLOCK" ] || [ ! -d "$CONNLOCKDIR" ] ; then
JOT='/usr/bin/jot' JOT='/usr/bin/jot'
if [ ! -x "$JOT" ] ; then if [ ! -x "$JOT" ] ; then
# no flock or jot, simply invoke ctlexec() # no flock or jot, simply invoke ctlexec()
CTL_CONN="ctl-${ERLANG_NODE}" CTL_CONN="ctl-${ERLANG_NODE}"
ctlexec $CTL_CONN $COMMAND ctlexec $CTL_CONN $COMMAND
result=$? result=$?
else else
# no flock, but at least there is jot # no flock, but at least there is jot
RAND=`jot -r 1 0 $MAXCONNID` RAND=`jot -r 1 0 $MAXCONNID`
CTL_CONN="ctl-${RAND}-${ERLANG_NODE}" CTL_CONN="ctl-${RAND}-${ERLANG_NODE}"
ctlexec $CTL_CONN $COMMAND ctlexec $CTL_CONN $COMMAND
result=$? result=$?
fi fi
else else
# we have flock so we get a lock # we have flock so we get a lock
# on one of a limited number of # on one of a limited number of
# 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"
( (
exec 8>"$CTL_LOCKFILE" exec 8>"$CTL_LOCKFILE"
if flock --nb 8; then if flock --nb 8; then
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...
badlock=1 badlock=1
else else
badlock="" badlock=""
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
exit 1; exit 1;
fi fi
case $result in case $result in
0) :;; 0) :;;
1) :;; 1) :;;
2) help;; 2) help;;
3) help;; 3) help;;
esac esac
return $result return $result
} }
ctlexec () ctlexec()
{ {
CONN_NAME=$1; shift CONN_NAME=$1; shift
COMMAND=$@ COMMAND=$@
@ -335,17 +341,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 +374,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 +384,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

View File

@ -5,6 +5,24 @@
%%% %%%
%%% @end %%% @end
%%% Created : 12 May 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net> %%% Created : 12 May 2013 by Evgeniy Khramtsov <ekhramtsov@process-one.net>
%%%
%%% ejabberd, Copyright (C) 2013 ProcessOne
%%%
%%% This program is free software; you can redistribute it and/or
%%% modify it under the terms of the GNU General Public License as
%%% published by the Free Software Foundation; either version 2 of the
%%% License, or (at your option) any later version.
%%%
%%% This program is distributed in the hope that it will be useful,
%%% but WITHOUT ANY WARRANTY; without even the implied warranty of
%%% MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
%%% General Public License for more details.
%%%
%%% You should have received a copy of the GNU General Public License
%%% along with this program; if not, write to the Free Software
%%% Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
%%% 02111-1307 USA
%%%------------------------------------------------------------------- %%%-------------------------------------------------------------------
-module(ejabberd_logger). -module(ejabberd_logger).

View File

@ -1,19 +1,22 @@
%% ``The contents of this file are subject to the Erlang Public License, %%% ====================================================================
%% Version 1.1, (the "License"); you may not use this file except in %%% ``The contents of this file are subject to the Erlang Public License,
%% compliance with the License. You should have received a copy of the %%% Version 1.1, (the "License"); you may not use this file except in
%% Erlang Public License along with this software. If not, it can be %%% compliance with the License. You should have received a copy of the
%% retrieved via the world wide web at http://www.erlang.org/. %%% Erlang Public License along with this software. If not, it can be
%% %%% retrieved via the world wide web at http://www.erlang.org/.
%% %%%
%% Software distributed under the License is distributed on an "AS IS" %%%
%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See %%% Software distributed under the License is distributed on an "AS IS"
%% the License for the specific language governing rights and limitations %%% basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
%% under the License. %%% the License for the specific language governing rights and limitations
%% %%% under the License.
%% %%%
%% The Initial Developer of the Original Code is ProcessOne. %%%
%% Portions created by ProcessOne are Copyright 2006-2013, ProcessOne %%% The Initial Developer of the Original Code is ProcessOne.
%% All Rights Reserved.'' %%% Portions created by ProcessOne are Copyright 2006-2013, ProcessOne
%%% All Rights Reserved.''
%%%
%%% This software is copyright 2006-2013, ProcessOne.
-module(p1_mnesia). -module(p1_mnesia).