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,
# 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

View File

@ -6,24 +6,45 @@ SMP=auto
ERL_MAX_PORTS=32000
ERL_PROCESSES=250000
ERL_MAX_ETS_TABLES=1400
SCRIPT_DIR=$(cd ${0%/*} && pwd)
FIREWALL_WINDOW=""
INET_DIST_INTERFACE="127.0.0.1"
ERLANG_NODE=ejabberd@localhost
# define default environment variables
NODE=ejabberd
HOST=localhost
ERLANG_NODE=$NODE@$HOST
SCRIPT_DIR=`cd ${0%/*} && pwd`
ERL={{erl}}
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
ARGS=
ARGS=""
while [ $# -ne 0 ] ; do
PARAM=$1
shift
case $PARAM in
--) break ;;
--node) ERLANG_NODE_ARG=$1; shift ;;
--node) ERLANG_NODE_ARG=$1 ; shift ;;
--config-dir) ETCDIR=$1 ; shift ;;
--config) EJABBERD_CONFIG_PATH=$1 ; shift ;;
--ctl-config) EJABBERDCTL_CONFIG_PATH=$1 ; shift ;;
@ -37,13 +58,15 @@ done
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 [ -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
LOGS_DIR={{localstatedir}}/log/ejabberd
fi
@ -57,60 +80,26 @@ 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
EJABBERDDIR={{libdir}}/ejabberd
fi
if [ "$EJABBERD_EBIN_PATH" = "" ] ; then
EJABBERD_EBIN_PATH=$EJABBERDDIR/ebin
EJABBERD_EBIN_PATH=$EJABBERDDIR/ebin
fi
if [ "$EJABBERD_PRIV_PATH" = "" ] ; then
EJABBERD_PRIV_PATH=$EJABBERDDIR/priv
EJABBERD_PRIV_PATH=$EJABBERDDIR/priv
fi
if [ "$EJABBERD_BIN_PATH" = "" ] ; then
EJABBERD_BIN_PATH=$EJABBERD_PRIV_PATH/bin
EJABBERD_BIN_PATH=$EJABBERD_PRIV_PATH/bin
fi
if [ "$EJABBERD_SO_PATH" = "" ] ; then
EJABBERD_SO_PATH=$EJABBERD_PRIV_PATH/lib
EJABBERD_SO_PATH=$EJABBERD_PRIV_PATH/lib
fi
if [ "$EJABBERD_MSGS_PATH" = "" ] ; then
EJABBERD_MSGS_PATH=$EJABBERD_PRIV_PATH/msgs
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"`
@ -118,11 +107,29 @@ 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"
# 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#*-}"
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
[ -d $HOME ] || $EXEC_CMD "mkdir -p $HOME"
cd $HOME
# export global variables
@ -141,16 +148,10 @@ export ERL_MAX_ETS_TABLES
export HOME
export EXEC_CMD
# Compatibility in ZSH
#setopt shwordsplit 2>/dev/null
# start server
start ()
start()
{
checknodenameusage
[ "$?" -eq 0 ] && echo "\nERROR: The node '$ERLANG_NODE' is already running." && return 1
check_start
$EXEC_CMD "$ERL \
$NAME $ERLANG_NODE \
-noinput -detached \
@ -163,7 +164,7 @@ start ()
}
# attach to server
debug ()
debug()
{
echo "--------------------------------------------------------------------"
echo ""
@ -182,7 +183,7 @@ debug ()
echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press any key to continue"
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
read foo
read foo
fi
echo ""
TTY=`tty | sed -e 's/.*\///g'`
@ -195,11 +196,9 @@ debug ()
}
# start interactive server
live ()
live()
{
checknodenameusage
[ "$?" -eq 0 ] && echo "\nERROR: The node '$ERLANG_NODE' is already running." && return 1
check_start
echo "--------------------------------------------------------------------"
echo ""
echo "IMPORTANT: ejabberd is going to start in LIVE (interactive) mode."
@ -216,7 +215,7 @@ live ()
echo " EJABBERD_BYPASS_WARNINGS=true"
echo "Press any key to continue"
if [ "$EJABBERD_BYPASS_WARNINGS" != "true" ] ; then
read foo
read foo
fi
echo ""
$EXEC_CMD "$ERL \
@ -228,7 +227,14 @@ live ()
$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 "Commands to start an ejabberd node:"
@ -247,7 +253,7 @@ help ()
}
# common control function
ctl ()
ctl()
{
COMMAND=$@
@ -258,71 +264,71 @@ ctl ()
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
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
# 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
ssresult=`expr $ssresult \* 10`
exit $ssresult
else
exit 1
fi
)
result=$?
if [ $result -eq 1 ]; then
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)
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;
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;;
0) :;;
1) :;;
2) help;;
3) help;;
esac
return $result
}
ctlexec ()
ctlexec()
{
CONN_NAME=$1; shift
COMMAND=$@
@ -335,17 +341,30 @@ ctlexec ()
-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
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
@ -355,9 +374,9 @@ wait_for_status()
# return: 0 OK, 1 KO
timeout=$2
status=4
while [ $status -ne $1 ]; do
while [ $status -ne $1 ] ; do
sleep $3
timeout=$(($timeout - 1))
timeout=`expr $timeout - 1`
[ $timeout -eq 0 ] && {
status=$1
} || {
@ -365,28 +384,16 @@ wait_for_status()
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 "
[ $timeout -eq 0 ] && return 1 || return 0
}
# main handler
case $ARGS in
' start') start;;
' debug') debug;;
' live') live;;
' etop') etop;;
' 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;;
esac

View File

@ -5,6 +5,24 @@
%%%
%%% @end
%%% 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).

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
%% compliance with the License. You should have received a copy of the
%% 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
%% 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
%% All Rights Reserved.''
%%% ====================================================================
%%% ``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
%%% compliance with the License. You should have received a copy of the
%%% 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
%%% 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
%%% All Rights Reserved.''
%%%
%%% This software is copyright 2006-2013, ProcessOne.
-module(p1_mnesia).