Uh oh... I may have opened a can of worms.
I mentioned in my earlier posts that we are running on Debian Linux, but I
carefully avoided discussing the implications of that. For a number of
reasons, partly philosophical and partly legal, Debian handles Java (and,
therefore, all Java applications) rather specially. Keep in mind as you
read this that Debian is the basis for a number of major distributions,
including the official Corel and Hewlett-Packard distributions, so much of
this probably applies to such Debian-derived distributions also.
Although this posting is mine and I take full responsibility for it, you
can read Stephane Bortzmeyer's proposed Debian Java Policy (DJP) here:
http://people.debian.org/~bortz//Java/policy.html
The central goal of the DJP is to make Debian virtual-machine agnostic.
That is, there should generally be no assumptions about which JVM/JDK
implementation is installed, and packages which require Java should be
installable on any JVM which can run them. This is especially important
to the Debian Project because most JVMs/JDKs have licensing restrictions
which preclude their inclusion as part of the Debian distribution itself,
and with one exception (Kaffe) are not themselves Open Source.
In order to achieve this, Debian uses its existing "alternatives" facility
to support transparent configuration. Special packages can be installed
to satisfy package dependencies, "java-virtual-machine-dummy" and
"java-compiler-dummy." The most important practical effect of this is
that the CLASSPATH is set _after_ invoking java! That is, the commands
"java" and "javac" are actually implemented as symbolic links from
/usr/bin/java and /usr/bin/javac to /etc/alternatives/java and
/etc/alternatives/javac, respectively, which are symbolic links to
/usr/bin/java-vm and /usr/bin/java-c. These, in turn, are actually shell
scripts which read configuration files /etc/java-vm and /etc/java-c to
find out where the Java binary is, how to set the CLASSPATH, and whether
to append the Debian Java repository (/usr/share/java/repository) to the
CLASSPATH. While this may seem a bit complicated, it is important to
understand that a great deal of power and convenience results from this
system, and it is possible to switch JVMs in a few seconds for testing.
For example, we have several versions of both the IBM and Sun JDKs
installed and a single symbolic link selects which one will be invoked.
On the other hand, this means that the startup script for jBoss must make
no assumptions about whether jBoss is running with Tomcat or Jetty, nor
even which JVM will be used. In addition, while it is comparatively easy
to have jBoss started manually by a script, in order to make jBoss come up
automatically on boot requires that this be done in a way compatible with
the distribution boot policies. Debian provides a utility to manage
server process startup on boot, "start-stop-daemon," which has certain
incompatibilities with jBoss' own shell scripts. The PATH and pwd may
need to be set explicitly when running a boot script, for example, as
"start-stop-daemon" regards the root directory as its home.
In addition, system configuration scripts in /etc/init.d are subject to
some extremely demanding constraints, especially that they must not hang
under any circumstances. If a boot script hangs on startup, the machine
will not be able to boot (except by manual runlevel override); if a boot
script hangs on shutdown, the machine may not be able to close and
dismount its filesystems cleanly. When trying to stop jBoss, the script
must make sure that it waits for jBoss to exit gracefully before allowing
the system shutdown to continue, or we risk having the database back-end
or even the mounted filesystems ripped away before jBoss is ready. On the
other hand, we cannot wait indefinitely for a graceful shutdown of jBoss,
since it could be wedged to tbe point where it will never exit.
Finally, since "start-stop-daemon" is spawning a shell script which wraps
the shell scripts which come with jBoss, and the whole point of using the
"start-stop-daemon" utility is to disconnect the shell script from any
terminal, sending a signal to the wrapper shell script does not cause
jBoss itself to terminate. In order to deal with this problem, we have
little alternative but to have "start-stop-daemon" send SIGTERM to all of
the instances of the JVM -- the lightweight processes or threads of jBoss
-- which are owned by the "jboss" system user. Remember that jBoss itself
might be in some state in which SIGTERM is not being handled correctly, in
which case we may eventually have to send SIGKILL, and that by this point
the behavior and stability of the JVM itself may be in serious question.
I was involved on this mailing list some weeks ago in an extensive
discussion about the safety and appropriateness of doing this, and I will
not rehash that issue here.
Anyway, here is the script which we have in current use and have had in
use successfully for some time. I have delimited the beginning and end of
the script with a row of "xxxx," but these are for clarity in this message
only and are not part of the script.
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
#!/bin/sh
#
# By Michael Bilow, <[EMAIL PROTECTED]>, 2001-05-09
# This Debian init script is in the public domain
#
# Loosely based upon prior contributed work by [EMAIL PROTECTED]
# which was published into the public domain on SourceForge:
# http://www.mail-archive.com/jboss-user%40lists.sourceforge.net/msg02919.html
#
###############################################################
#
# Install this script into /etc/init.d and create links to
# start and stop with position control values 95 and 15,
# respectively. Use the 'update-rc.d' utility to do this:
#
# update-rc.d jboss_local defaults 95 15
#
###############################################################
#
# We are assuming also that a system user "jboss" has been
# created with group "jboss," and that the jBoss tree has been
# installed in such a way that the "jboss" user has necessary
# access to run it. We choose to have most of the jBoss tree
# owned by "root" with owner group "jboss," and then to grant
# either read-only or read-write privilege to the "jboss" group
# as needed. The details of this installation are beyond the
# scope of this comment. The "jboss" user should NOT have any
# privilege to log in.
#
# If jBoss/Tomcat absolutely must attach a listener directly
# to port 80 or some other privileged port, use the "ipchains"
# facility rather than running as root. For example, configure
# jBoss/Tomcat to listen on port 10080 and then issue:
#
# ipchains -A input --destination-port 80 -p tcp -j REDIRECT 10080
#
###############################################################
#
# Since 'start-stop-daemon' will make / the pwd for the
# backgrounded process when the '--background' switch is used,
# we need to have a wrapper script 'debian_wrapper.sh' which
# contains simply:
#
# #!/bin/sh
# cd $DAEMONPATH
# ./run_with_tomcat.sh
#
# This wrapper script needs its ownership and permissions such
# that the "jboss" user can read and execute it, and it must be
# placed into the directory where 'run_with_tomcat.sh' resides.
#
###############################################################
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
export DAEMONPATH=/var/local/jboss/tomcat/jboss/bin/
DAEMONNAME=debian_wrapper.sh
DAEMON="${DAEMONPATH}${DAEMONNAME}"
PKGNAME="jboss_local"
JVM=java # Name of the running JVM in /proc/<pid>/stat
DESC="jBoss with Tomcat application server"
LIMIT=300 # Seconds we try sending SIGTERM before sending SIGKILL
test -x $DAEMON || exit 0
set -e
case "$1" in
start)
echo -n "Starting $DESC: "
start-stop-daemon --quiet --start --background \
--chuid jboss --exec $DAEMON
echo "$PKGNAME."
;;
stop)
echo -n "Stopping $DESC: "
# 'date +%s' gives seconds since Unix epoch
STOPSTAMP=`date +%s`
STOPLIMIT=`expr $LIMIT + $STOPSTAMP`
if start-stop-daemon --quiet --stop --signal 0 \
--user jboss --name $JVM
then
start-stop-daemon --quiet --stop --oknodo \
--user jboss --name $JVM
# jBoss could take considerable time to shut down
while start-stop-daemon --quiet --stop --signal 0 \
--user jboss --name $JVM 2>/dev/null
do
if [ `date +%s` -le $STOPLIMIT ]
then
sleep 1
echo -n "."
else
start-stop-daemon --quiet --stop --signal 9 \
--user jboss --name $JVM --oknodo
fi
done
echo "$PKGNAME."
else
echo "$PKGNAME was not running."
fi
;;
restart|force-reload)
echo -n "Restarting $DESC: "
$0 stop
sleep 3
$0 start
;;
*)
N=/etc/init.d/$PKGNAME
echo "Usage: $N {start|stop|restart|force-reload}" >&2
exit 1
;;
esac
exit 0
xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
Note that there are certain aspects of this script which remain in doubt.
For example, it is not clear whether "restart" works in all cases because
jBoss might not cleanly release and unbind the sockets it was using for
its listeners, requiring that the sockets go through a TIME_WAIT stage
before they can be reacquired and bound to the new server instance. In
this case, the "sleep 3" in the restart code may need to be lengthened.
Also, since jBoss is not (yet) an official Debian package, the use of 95
and 15 to control the start and stop order relative to other packages is a
matter of trial and error on my part, and these numbers are not registered
with Debian. As a result, these may not work on a differently configured
system. This is not a major issue, since we tend to start and stop jBoss
by invoking this script manually quite often. Nevertheless, I want jBoss
to start in runlevel 2 after Apache (S91) and to stop on halt or reboot
before BIND (K19) and PostgreSQL (K20); the procedure is documented in
/usr/share/doc/sysvinit/README.runlevels.gz on an installed Debian system.
The use of a Debian wrapper script, debian_wrapper.sh, was a choice I made
so as to avoid having to modify the scripts such as "run.sh" which come
supplied with jBoss. This is intended to ease the process of upgrading
jBoss without having to merge changes manually. Note that Debian packages
have the notion of a "conffile," which is upgraded automatically on a
package upgrade if it has not been modified since the prior installation:
the MD5 digest of all conffiles as they were originally installed is
maintained for each package so it can be determined easily if they have
been modified. If the conffile has been modified since installation, then
the administrator is prompted to decide how to handle this as part of the
upgrade process.
The most important feature is that, after sending SIGTERM to the running
JVM containing jBoss, the script waits $LIMIT seconds -- I am using 300
seconds, or 5 minutes -- for jBoss to stop. Usually, jBoss will stop
gracefully in 15-30 seconds and close the database properly, but if not
then it is important to see that jBoss goes down one way or another and
that this script exits.
While this may seem a bit opaque, I believe that Debian Linux is an
extremely important platform which is emerging as the de facto reference
platform for Linux. Debian has clearly enunciated design goals which make
quite a lot of technical sense. As a result, I feel it is important to
see that this is done correctly.
-- Mike
On 2001-06-21 at 18:19 -0400, David Ward wrote:
> Here's a better one (more configurable, provides more vars at the top
> and runs as whoever you specify). I would still like to hear from
> someone who knows jboss better to tell me that yes, this is a safe way
> to stop things. (I did just recently see a posting before mine with
> someone else who does this; so I'm guessing it's okay...)
>
> =================================
>
> #!/bin/sh
>
> JAVA_HOME=/usr/java/jdk1.3.1
> JBOSS_HOME=/data/packages/JBoss-2.2.2_Tomcat-3.2.2/jboss
> JBOSS_USER=jboss
> JBOSS_HOST=localhost
> JBOSS_PORT=8082
> JBOSS_LOG=/tmp/jboss.log
>
> case "$1" in
> start)
> DIR=`pwd`
> cd $JBOSS_HOME/bin
> su -c "nohup ./run_with_tomcat.sh 1> $JBOSS_LOG 2>&1 &" $JBOSS_USER
> cd $DIR
> ;;
> stop)
> $JAVA_HOME/bin/java -cp $JBOSS_HOME/lib/ext/jboss.jar
>org.jboss.Shutdown
> $JBOSS_HOST $JBOSS_PORT
> ;;
> *)
> echo "Usage: $0 {start|stop}"
> exit 1
> esac
>
> ================================
>
> David Ward wrote:
>
> > I've looked through the mail archives, and it looks like people's
> > previous attempts at a jboss start/stop script suitable for /etc/init.d
> > are overly complex, especially since they are copying what's in the run
> > scripts and if JBoss decides to change those, people's custom scripts
> > have to change.
> >
> > So.... here's something a bit easier I threw together (only tested on
> > RedHat Linux 7.1):
> >
> > -- snip --
> >
> > #!/bin/sh
> >
> > export JAVA_HOME=/usr/java/jdk1.3.1
> > export JBOSS_HOME=/data/packages/JBoss-2.2.2_Tomcat-3.2.2/jboss
> >
> > case "$1" in
> > start)
> > DIR=`pwd`
> > cd $JBOSS_HOME/bin
> > nohup ./run_with_tomcat.sh 1> /tmp/jboss.log 2>&1 &
> > cd $DIR
> > ;;
> > stop)
> > $JAVA_HOME/bin/java -cp $JBOSS_HOME/lib/ext/jboss.jar
> > org.jboss.Shutdown
> > ;;
> > *)
> > echo "Usage: $0 {start|stop}"
> > exit 1
> > esac
> >
> > -- snip --
> >
> > The only thing I see funky happening is that I get a lot less output on
> > shutdown then when I used to do a Control-C. Is this OK?
> >
> > Also, if you have a jboss user (or nobody user) that you'd rather this
> > process run as, you might want to "su -c" (or something similar) the
> > process.
> >
> > Hope this helps,
> > David
_______________________________________________
JBoss-user mailing list
[EMAIL PROTECTED]
http://lists.sourceforge.net/lists/listinfo/jboss-user