Bug in Redhat init script

The redhat init script is incorrect and does not work with OpenSUSE under systemd. Looking into it, I found that the problem is that the pidfile is not persistent - it is only created upon shutdown and then immediately removed, as a foil for kill proc.

I submitted a patch through the opensuse build system that fixes this problem - it probably should be rolled upstream. The opensuse build request is at https://build.opensuse.org/request/show/223463. I’m not providing a diff here because the diff in the opensuse build file is predicated upon a couple of additional patches. But here is the init script I’m using. It works correctly on opensuse, and should not work incorrectly anywhere else, either.

arguably status() should be a little smarter in checking the pidfile to see if it matches the running process (if there is one), and start() should be a little smarter in checking for an existing pidfile, but I don’t have the time to make it completely buttoned down for now…

#!/bin/sh
#
# openfire      Stops and starts the Openfire XMPP service.
#
# chkconfig: 2345 99 1
# description: Openfire is an XMPP server, which is a server that facilitates \
#              XML based communication, such as chat.
# config: /opt/openfire/conf/openfire.xml
# config: /etc/sysconfig/openfire
# pidfile: /var/run/openfire.pid
#
# This script has currently been tested on Redhat, CentOS, and Fedora  based
# systems.
# #####
# Begin setup work
##### # Initialization
PATH="/sbin:/bin:/usr/bin:/usr/sbin"
RETVAL=0 # Check that we are root ... so non-root users stop here.
if [ "`id -u`" != 0 ]; then
        echo $0 must be run as root
        exit 1
fi # Get config.
[ -f "/etc/sysconfig/openfire" ] && . /etc/sysconfig/openfire
if [ -f "/etc/init.d/functions" ]; then
  FUNCTIONS_FOUND=true
  . /etc/init.d/functions
fi # If openfire user is not set in sysconfig, set to daemon.
[ -z "$OPENFIRE_USER" ] && OPENFIRE_USER="daemon" # If pid file path is not set in sysconfig, set to /var/run/openfire.pid.
[ -z "$OPENFIRE_PIDFILE" ] && OPENFIRE_PIDFILE="/var/run/openfire.pid" # ----------------------------------------------------------------- # If a openfire home variable has not been specified, try to determine it.
if [ -z "$OPENFIRE_HOME" -o ! -d "$OPENFIRE_HOME" ]; then
        if [ -d "/usr/share/openfire" ]; then
                OPENFIRE_HOME="/usr/share/openfire"
        elif [ -d "/usr/local/openfire" ]; then
                OPENFIRE_HOME="/usr/local/openfire"
        elif [ -d "/opt/openfire" ]; then
                OPENFIRE_HOME="/opt/openfire"
        else
                echo "Could not find Openfire installation under /opt, /usr/share, or /usr/local."
                echo "Please specify the Openfire installation location as variable OPENFIRE_HOME"
                echo "in /etc/sysconfig/openfire."
                exit 1
        fi
fi # If log path is not set in sysconfig, set to $OPENFIRE_HOME/logs.
[ -z "$OPENFIRE_LOGDIR" ] && OPENFIRE_LOGDIR="${OPENFIRE_HOME}/logs" # Attempt to locate java installation.
if [ -z "$JAVA_HOME" ]; then
        if [ -d "${OPENFIRE_HOME}/jre" ]; then
                JAVA_HOME="${OPENFIRE_HOME}/jre"
        elif [ -d "/etc/alternatives/jre" ]; then
                JAVA_HOME="/etc/alternatives/jre"
        else
                jdks=`ls -r1d /usr/java/j*`
                for jdk in $jdks; do
                        if [ -f "${jdk}/bin/java" ]; then
                                JAVA_HOME="$jdk"
                                break
                        fi
                done
        fi
fi
JAVACMD="${JAVA_HOME}/bin/java" if [ ! -d "$JAVA_HOME" -o ! -x "$JAVACMD" ]; then
        echo "Error: JAVA_HOME is not defined correctly."
        echo "       Can not sure execute $JAVACMD."
        exit 1
fi # Prepare location of openfire libraries
OPENFIRE_LIB="${OPENFIRE_HOME}/lib" # Prepare openfire command line
OPENFIRE_OPTS="${OPENFIRE_OPTS} -DopenfireHome=${OPENFIRE_HOME} -Dopenfire.lib.dir=${OPENFIRE_LIB}" # Prepare local java class path
if [ -z "$LOCALCLASSPATH" ]; then
        LOCALCLASSPATH="${OPENFIRE_LIB}/startup.jar"
else
        LOCALCLASSPATH="${OPENFIRE_LIB}/startup.jar:${LOCALCLASSPATH}"
fi # Export any necessary variables
export JAVA_HOME JAVACMD # Lastly, prepare the full command that we are going to run.
OPENFIRE_RUN_CMD="${JAVACMD} -server ${OPENFIRE_OPTS} -classpath \"${LOCALCLASSPATH}\" -jar \"${OPENFIRE_LIB}/startup.jar\"" #####
# End setup work
##### start() {
        OLD_PWD=`pwd`
        cd $OPENFIRE_LOGDIR         PID=$(findPID)
        if [ -n "$PID" ]; then
            echo "Openfire is already running."
            RETVAL=1
            return
        fi         # Start daemons.
        echo -n "Starting openfire: "         rm -f nohup.out
        su -s /bin/sh -c "nohup $OPENFIRE_RUN_CMD > $OPENFIRE_LOGDIR/nohup.out 2>&1 &" $OPENFIRE_USER
        RETVAL=$?         echo         [ $RETVAL -eq 0 -a -d /var/run ] && touch /var/run/openfire         sleep 1 # allows prompt to return         PID=$(findPID)
        echo $PID > $OPENFIRE_PIDFILE         cd $OLD_PWD
} stop() {
        # Stop daemons.
        echo -n "Shutting down openfire: "         if [ -f "$OPENFIRE_PIDFILE" ]; then
                killproc -p $OPENFIRE_PIDFILE -d 10
                rm -f $OPENFIRE_PIDFILE
        else
                PID=$(findPID)
                if [ -n $PID ]; then
                        kill $PID
                else
                        echo "Openfire is not running."
                fi
        fi         RETVAL=$?
        echo         [ $RETVAL -eq 0 -a -f "/var/run/openfire" ] && rm -f /var/run/openfire
} restart() {
        stop
        sleep 10 # give it a few moments to shut down
        start
} condrestart() {
        [ -e "/var/run/openfire" ] && restart
        return 0
} status() {
        PID=$(findPID)
        if [ -n "$PID" ]; then
                echo "openfire is running"
                RETVAL=0
        else
                echo "openfire is not running"
                RETVAL=1
        fi
} findPID() {
        echo `ps ax --width=1000 | grep openfire | grep startup.jar | awk '{print $1}'`
} # Handle how we were called.
case "$1" in
        start)
                start
                ;;
        stop)
                stop
                ;;
        restart)
                restart
                ;;
        condrestart)
                condrestart
                ;;
        reload)
                restart
                ;;
        status)
                status
                ;;
        *)
                echo "Usage $0 {start|stop|restart|status|condrestart|reload}"
                RETVAL=1
esac exit $RETVAL

the current init script in openfire is for RHEL/CentOS, not OpenSuse (although I do understand OpenSuse has commonalities). Also, the current init script was designed for SystemV, not systemd, although systemd should have backwards compatability to my understanding.

With that said, I know some other forums users have had difficulties with the init script working on systemd machines (such as Fedora, and now OpenSuse, and others will come since now Debian has decided on systemd and so will others). So, a complete new script may be needed for systemd users.

If you can put together a new full working systemd-compatible init script, I’m sure it will be very helpful for a lot of users. The existing SystemV script should be kept since some OS’s like RHEL and CentOS will likely not make the systemd swtich for some time still.

I would maintain that the specific parts of the script that I modified are even not optimal under RedHat. Specifically, I don’t understand why the pidfile is not dropped in on the start of the program, and removed after the program is finished. Currently, the pidfile is only created so that killproc can do its thing, and otherwise it uses $(findPID) to dynamically grab the pid. I can see how this could work most of the time, but it’s also kind of opposite to the way RedHat-like init scripts usually do things in my experience (and systemd appears to actually expect this).

That said, the script that I provided does also have a couple of OpenSUSE specific patches, and I probably should remove those and send you a virgin diff.

A systemd specific script would be good, and maybe I’ll poke at that when I get some time, but for now, for me, it’s sufficient that the SystemV init script behaves nicely when it’s invoked by systemd.

You could be very right. I don’t know who wrote the RHEL init script originally, it could of been somebody with a need and cared to share it with the community, or it was good enough at the time, etc. I must say, the current RHEL init script “works for me”. But that doesn’t mean it’s as good as it could be of course.

If you have time, I think the community would greatly appreciate it if you:

  1. Posted a OpenSuse specific init script (sounds like there are subtleties you faced when getting it to work, perhaps enough to warrant it’s own script perhaps)

  2. Posted a Diff and/or a new init script for systemd systems (there will be more and more systemd systems as time goes on)

  3. Posted a diff to fix the current RHEL/CentOS SystemV init script

You had mentioned before that you submitted “upstream” some patches for the init scripts to OpenSuse. I imagine someone at Suse, or a community member is packaging openfire into your repos… this would not be “upstream” for the Openfire project and thusly your patches would never make it into Openfire codebase. If they are good patches, we would want to get them into the codebase so that others can enjoy nice init scripts

You misunderstand - THIS is my attempt to submit patches upstream.

I’ll work on it as I get a chance and post some diffs.

Ah, I see now

Well, in any regard, it sounds like you have some good contributions that would really help out a lot of people. Not to mention you will get your name attached to the fixes (who doesn’t like a little recognition?)

The openfire project is using SVN at the moment for version control, so unified diff/patch files are the choice for submissions. New init scripts should just be uploaded as a complete file.

To attach/upload things, click the “undefined” button in the top right corner.

I used to work for Jive. There’s probably a bit too much recognition going on now. But your point is taken. It won’t be too hard to diff my changes against the stock file.

“Russell, oh where have you been all these years!? Ignite wants you back!” lol

Didn’t know you were a Jiver. It’s nice to have you contributing to the community

Attached is a patch for case 3.

Note that the change is actually a generic one - I intentionally left out patches for opensuse specifically, though there are two or three available from the package that I’ll submit as I have time (though I’m not the one who wrote them). This particular fix should apply to all sysvinint and systemd installs including RedHat, Centos, Fedora, etc., but feel free to test.
openfire-systemd.patch.zip (629 Bytes)

Thanks Russell. I’ll make sure one of the OF guys sees this for review and testing. If all is well, it should get pulled in.

OF-753 thanks, but your patch appears to be backwards. The simpliest thing to do is checkout svn trunk and then svn diff your modified file.

Sorry. Try this one.
openfire.patch.zip (595 Bytes)

thanks, committed

old programmers come back?

people come to igniterealtime, but never leave! muwahahahahahah! (evil laugh)

I wasn’t a programmer, I was actually a hosting engineer.

We actually have more than one openfire install, so odds are I’ll have more stuff for you at some point.