1#!/usr/local/bin/bash
2
3# LSB Tags
4### BEGIN INIT INFO
5# Provides:          jetty
6# Required-Start:    $local_fs $network
7# Required-Stop:     $local_fs $network
8# Default-Start:     2 3 4 5
9# Default-Stop:      0 1 6
10# Short-Description: Jetty start script.
11# Description:       Start Jetty web server.
12### END INIT INFO
13
14# Startup script for jetty under *nix systems (it works under NT/cygwin too).
15
16##################################################
17# Set the name which is used by other variables.
18# Defaults to the file name without extension.
19##################################################
20NAME=$(echo $(basename $0) | sed -e 's/^[SK][0-9]*//' -e 's/\.sh$//')
21
22# To get the service to restart correctly on reboot, uncomment below (3 lines):
23# ========================
24# chkconfig: 3 99 99
25# description: Jetty 9 webserver
26# processname: jetty
27# ========================
28
29# Configuration files
30#
31# /etc/default/$NAME
32#   If it exists, this is read at the start of script. It may perform any
33#   sequence of shell commands, like setting relevant environment variables.
34#
35# $HOME/.$NAMErc (e.g. $HOME/.jettyrc)
36#   If it exists, this is read at the start of script. It may perform any
37#   sequence of shell commands, like setting relevant environment variables.
38#
39# /etc/$NAME.conf
40#   If found, and no configurations were given on the command line,
41#   the file will be used as this script's configuration.
42#   Each line in the file may contain:
43#     - A comment denoted by the pound (#) sign as first non-blank character.
44#     - The path to a regular file, which will be passed to jetty as a
45#       config.xml file.
46#     - The path to a directory. Each *.xml file in the directory will be
47#       passed to jetty as a config.xml file.
48#     - All other lines will be passed, as-is to the start.jar
49#
50#   The files will be checked for existence before being passed to jetty.
51#
52# Configuration variables
53#
54# JAVA
55#   Command to invoke Java. If not set, java (from the PATH) will be used.
56#
57# JAVA_OPTIONS
58#   Extra options to pass to the JVM
59#
60# JETTY_HOME
61#   Where Jetty is installed. If not set, the script will try go
62#   guess it by looking at the invocation path for the script
63#   The java system property "jetty.home" will be
64#   set to this value for use by configure.xml files, f.e.:
65#
66#    <Arg><Property name="jetty.home" default="."/>/webapps/jetty.war</Arg>
67#
68# JETTY_BASE
69#   Where your Jetty base directory is.  If not set, the value from
70#   $JETTY_HOME will be used.
71#
72# JETTY_RUN
73#   Where the $NAME.pid file should be stored. It defaults to the
74#   first available of /var/run, /usr/var/run, JETTY_BASE and /tmp
75#   if not set.
76#
77# JETTY_PID
78#   The Jetty PID file, defaults to $JETTY_RUN/$NAME.pid
79#
80# JETTY_ARGS
81#   The default arguments to pass to jetty.
82#   For example
83#      JETTY_ARGS=jetty.http.port=8080 jetty.ssl.port=8443
84#
85# JETTY_USER
86#   if set, then used as a username to run the server as
87#
88# JETTY_SHELL
89#   If set, then used as the shell by su when starting the server.  Will have
90#   no effect if start-stop-daemon exists.  Useful when JETTY_USER does not
91#   have shell access, e.g. /bin/false
92#
93# JETTY_START_TIMEOUT
94#   Time spent waiting to see if startup was successful/failed. Defaults to 60 seconds
95#
96
97usage()
98{
99    echo "Usage: ${0##*/} [-d] {start|stop|run|restart|check|supervise} [ CONFIGS ... ] "
100    exit 1
101}
102
103[ $# -gt 0 ] || usage
104
105
106##################################################
107# Some utility functions
108##################################################
109findDirectory()
110{
111  local L OP=$1
112  shift
113  for L in "$@"; do
114    [ "$OP" "$L" ] || continue
115    printf %s "$L"
116    break
117  done
118}
119
120running()
121{
122  if [ -f "$1" ]
123  then
124    local PID=$(cat "$1" 2>/dev/null) || return 1
125    kill -0 "$PID" 2>/dev/null
126    return
127  fi
128  rm -f "$1"
129  return 1
130}
131
132started()
133{
134  # wait for 60s to see "STARTED" in PID file, needs jetty-started.xml as argument
135  for ((T = 0; T < $(($3 / 4)); T++))
136  do
137    sleep 4
138    [ -z "$(grep STARTED $1 2>/dev/null)" ] || return 0
139    [ -z "$(grep STOPPED $1 2>/dev/null)" ] || return 1
140    [ -z "$(grep FAILED $1 2>/dev/null)" ] || return 1
141    local PID=$(cat "$2" 2>/dev/null) || return 1
142    kill -0 "$PID" 2>/dev/null || return 1
143    echo -n ". "
144  done
145
146  return 1;
147}
148
149
150readConfig()
151{
152  (( DEBUG )) && echo "Reading $1.."
153  source "$1"
154}
155
156dumpEnv()
157{
158    echo "JAVA                  =  $JAVA"
159    echo "JAVA_OPTIONS          =  ${JAVA_OPTIONS[*]}"
160    echo "JETTY_HOME            =  $JETTY_HOME"
161    echo "JETTY_BASE            =  $JETTY_BASE"
162    echo "START_D               =  $START_D"
163    echo "START_INI             =  $START_INI"
164    echo "JETTY_START           =  $JETTY_START"
165    echo "JETTY_CONF            =  $JETTY_CONF"
166    echo "JETTY_ARGS            =  ${JETTY_ARGS[*]}"
167    echo "JETTY_RUN             =  $JETTY_RUN"
168    echo "JETTY_PID             =  $JETTY_PID"
169    echo "JETTY_START_LOG       =  $JETTY_START_LOG"
170    echo "JETTY_STATE           =  $JETTY_STATE"
171    echo "JETTY_START_TIMEOUT   =  $JETTY_START_TIMEOUT"
172    echo "RUN_CMD               =  ${RUN_CMD[*]}"
173}
174
175
176
177##################################################
178# Get the action & configs
179##################################################
180CONFIGS=()
181NO_START=0
182DEBUG=0
183
184while [[ $1 = -* ]]; do
185  case $1 in
186    -d) DEBUG=1 ;;
187  esac
188  shift
189done
190ACTION=$1
191shift
192
193##################################################
194# Read any configuration files
195##################################################
196ETC=/etc
197if [ $UID != 0 ]
198then
199  ETC=$HOME/etc
200fi
201
202for CONFIG in {/etc,~/etc}/default/${NAME}{,9} $HOME/.${NAME}rc /usr/local/etc/${NAME}/${NAME}{,9}; do
203  if [ -f "$CONFIG" ] ; then
204    readConfig "$CONFIG"
205  fi
206done
207
208
209##################################################
210# Set tmp if not already set.
211##################################################
212TMPDIR=${TMPDIR:-/tmp}
213
214##################################################
215# Jetty's hallmark
216##################################################
217JETTY_INSTALL_TRACE_FILE="start.jar"
218
219
220##################################################
221# Try to determine JETTY_HOME if not set
222##################################################
223if [ -z "$JETTY_HOME" ]
224then
225  JETTY_SH=$0
226  case "$JETTY_SH" in
227    /*)     JETTY_HOME=${JETTY_SH%/*/*} ;;
228    ./*/*)  JETTY_HOME=${JETTY_SH%/*/*} ;;
229    ./*)    JETTY_HOME=.. ;;
230    */*/*)  JETTY_HOME=./${JETTY_SH%/*/*} ;;
231    */*)    JETTY_HOME=. ;;
232    *)      JETTY_HOME=.. ;;
233  esac
234
235  if [ ! -f "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ]
236  then
237    JETTY_HOME=
238  fi
239fi
240
241
242##################################################
243# No JETTY_HOME yet? We're out of luck!
244##################################################
245if [ -z "$JETTY_HOME" ]; then
246  echo "** ERROR: JETTY_HOME not set, you need to set it or install in a standard location"
247  exit 1
248fi
249
250cd "$JETTY_HOME"
251JETTY_HOME=$PWD
252
253
254##################################################
255# Set JETTY_BASE
256##################################################
257if [ -z "$JETTY_BASE" ]; then
258  JETTY_BASE=$JETTY_HOME
259fi
260
261cd "$JETTY_BASE"
262JETTY_BASE=$PWD
263
264
265#####################################################
266# Check that jetty is where we think it is
267#####################################################
268if [ ! -r "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ]
269then
270  echo "** ERROR: Oops! Jetty doesn't appear to be installed in $JETTY_HOME"
271  echo "** ERROR:  $JETTY_HOME/$JETTY_INSTALL_TRACE_FILE is not readable!"
272  exit 1
273fi
274
275##################################################
276# Try to find this script's configuration file,
277# but only if no configurations were given on the
278# command line.
279##################################################
280if [ -z "$JETTY_CONF" ]
281then
282  if [ -f $ETC/${NAME}.conf ]
283  then
284    JETTY_CONF=$ETC/${NAME}.conf
285  elif [ -f "$JETTY_BASE/etc/jetty.conf" ]
286  then
287    JETTY_CONF=$JETTY_BASE/etc/jetty.conf
288  elif [ -f "$JETTY_HOME/etc/jetty.conf" ]
289  then
290    JETTY_CONF=$JETTY_HOME/etc/jetty.conf
291  fi
292fi
293
294#####################################################
295# Find a location for the pid file
296#####################################################
297if [ -z "$JETTY_RUN" ]
298then
299  JETTY_RUN=$(findDirectory -w /var/run /usr/var/run $JETTY_BASE /tmp)/jetty
300  [ -d "$JETTY_RUN" ] || mkdir $JETTY_RUN
301fi
302
303#####################################################
304# define start log location
305#####################################################
306if [ -z "$JETTY_START_LOG" ]
307then
308  JETTY_START_LOG="$JETTY_RUN/$NAME-start.log"
309fi
310
311#####################################################
312# Find a pid and state file
313#####################################################
314if [ -z "$JETTY_PID" ]
315then
316  JETTY_PID="$JETTY_RUN/${NAME}.pid"
317fi
318
319if [ -z "$JETTY_STATE" ]
320then
321  JETTY_STATE=$JETTY_BASE/${NAME}.state
322fi
323
324case "`uname`" in
325CYGWIN*) JETTY_STATE="`cygpath -w $JETTY_STATE`";;
326esac
327
328
329JETTY_ARGS=(${JETTY_ARGS[*]} "jetty.state=$JETTY_STATE")
330
331##################################################
332# Get the list of config.xml files from jetty.conf
333##################################################
334if [ -f "$JETTY_CONF" ] && [ -r "$JETTY_CONF" ]
335then
336  while read -r CONF
337  do
338    if expr "$CONF" : '#' >/dev/null ; then
339      continue
340    fi
341
342    if [ -d "$CONF" ]
343    then
344      # assume it's a directory with configure.xml files
345      # for example: /etc/jetty.d/
346      # sort the files before adding them to the list of JETTY_ARGS
347      for XMLFILE in "$CONF/"*.xml
348      do
349        if [ -r "$XMLFILE" ] && [ -f "$XMLFILE" ]
350        then
351          JETTY_ARGS=(${JETTY_ARGS[*]} "$XMLFILE")
352        else
353          echo "** WARNING: Cannot read '$XMLFILE' specified in '$JETTY_CONF'"
354        fi
355      done
356    else
357      # assume it's a command line parameter (let start.jar deal with its validity)
358      JETTY_ARGS=(${JETTY_ARGS[*]} "$CONF")
359    fi
360  done < "$JETTY_CONF"
361fi
362
363##################################################
364# Setup JAVA if unset
365##################################################
366if [ -z "$JAVA" ]
367then
368  JAVA=$(which java)
369fi
370
371if [ -z "$JAVA" ]
372then
373  echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." >&2
374  exit 1
375fi
376
377#####################################################
378# See if Deprecated JETTY_LOGS is defined
379#####################################################
380if [ "$JETTY_LOGS" ]
381then
382  echo "** WARNING: JETTY_LOGS is Deprecated. Please configure logging within the jetty base." >&2
383fi
384
385#####################################################
386# Set STARTED timeout
387#####################################################
388if [ -z "$JETTY_START_TIMEOUT" ]
389then
390  JETTY_START_TIMEOUT=60
391fi
392
393#####################################################
394# Are we running on Windows? Could be, with Cygwin/NT.
395#####################################################
396case "`uname`" in
397CYGWIN*) PATH_SEPARATOR=";";;
398*) PATH_SEPARATOR=":";;
399esac
400
401
402#####################################################
403# Add jetty properties to Java VM options.
404#####################################################
405
406case "`uname`" in
407CYGWIN*)
408JETTY_HOME="`cygpath -w $JETTY_HOME`"
409JETTY_BASE="`cygpath -w $JETTY_BASE`"
410TMPDIR="`cygpath -w $TMPDIR`"
411;;
412esac
413
414JAVA_OPTIONS=(${JAVA_OPTIONS[*]} "-Djetty.home=$JETTY_HOME" "-Djetty.base=$JETTY_BASE" "-Djava.io.tmpdir=$TMPDIR")
415
416#####################################################
417# This is how the Jetty server will be started
418#####################################################
419
420JETTY_START=$JETTY_HOME/start.jar
421START_INI=$JETTY_BASE/start.ini
422START_D=$JETTY_BASE/start.d
423if [ ! -f "$START_INI" -a ! -d "$START_D" ]
424then
425  echo "Cannot find a start.ini file or a start.d directory in your JETTY_BASE directory: $JETTY_BASE" >&2
426  exit 1
427fi
428
429case "`uname`" in
430CYGWIN*) JETTY_START="`cygpath -w $JETTY_START`";;
431esac
432
433RUN_ARGS=(${JAVA_OPTIONS[@]} -jar "$JETTY_START" ${JETTY_ARGS[*]})
434RUN_CMD=("$JAVA" ${RUN_ARGS[@]})
435
436#####################################################
437# Comment these out after you're happy with what
438# the script is doing.
439#####################################################
440if (( DEBUG ))
441then
442  dumpEnv
443fi
444
445##################################################
446# Do the action
447##################################################
448case "$ACTION" in
449  start)
450    echo -n "Starting Jetty: "
451
452    if (( NO_START )); then
453      echo "Not starting ${NAME} - NO_START=1";
454      exit
455    fi
456
457    if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1
458    then
459      unset CH_USER
460      if [ -n "$JETTY_USER" ]
461      then
462        CH_USER="-c$JETTY_USER"
463      fi
464
465      start-stop-daemon -S -p"$JETTY_PID" $CH_USER -d"$JETTY_BASE" -b -m -a "$JAVA" -- "${RUN_ARGS[@]}" start-log-file="$JETTY_START_LOG"
466
467    else
468
469      if running $JETTY_PID
470      then
471        echo "Already Running $(cat $JETTY_PID)!"
472        exit 1
473      fi
474
475      if [ -n "$JETTY_USER" ] && [ `whoami` != "$JETTY_USER" ]
476      then
477        unset SU_SHELL
478        if [ "$JETTY_SHELL" ]
479        then
480          SU_SHELL="-s $JETTY_SHELL"
481        fi
482
483        touch "$JETTY_PID"
484        chown "$JETTY_USER" "$JETTY_PID"
485        # FIXME: Broken solution: wordsplitting, pathname expansion, arbitrary command execution, etc.
486        su - "$JETTY_USER" $SU_SHELL -c "
487          cd \"$JETTY_BASE\"
488          exec ${RUN_CMD[*]} start-log-file=\"$JETTY_START_LOG\" > /dev/null &
489          disown \$!
490          echo \$! > \"$JETTY_PID\""
491      else
492        "${RUN_CMD[@]}" > /dev/null &
493        disown $!
494        echo $! > "$JETTY_PID"
495      fi
496
497    fi
498
499    if expr "${JETTY_ARGS[*]}" : '.*jetty-started.xml.*' >/dev/null
500    then
501      if started "$JETTY_STATE" "$JETTY_PID" "$JETTY_START_TIMEOUT"
502      then
503        echo "OK `date`"
504      else
505        echo "FAILED `date`"
506        exit 1
507      fi
508    else
509      echo "ok `date`"
510    fi
511
512    ;;
513
514  stop)
515    echo -n "Stopping Jetty: "
516    if [ $UID -eq 0 ] && type start-stop-daemon > /dev/null 2>&1; then
517      start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s HUP
518
519      TIMEOUT=30
520      while running "$JETTY_PID"; do
521        if (( TIMEOUT-- == 0 )); then
522          start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s KILL
523        fi
524
525        sleep 1
526      done
527    else
528      if [ ! -f "$JETTY_PID" ] ; then
529        echo "ERROR: no pid found at $JETTY_PID"
530        exit 1
531      fi
532
533      PID=$(cat "$JETTY_PID" 2>/dev/null)
534      if [ -z "$PID" ] ; then
535        echo "ERROR: no pid id found in $JETTY_PID"
536        exit 1
537      fi
538      kill "$PID" 2>/dev/null
539
540      TIMEOUT=30
541      while running $JETTY_PID; do
542        if (( TIMEOUT-- == 0 )); then
543          kill -KILL "$PID" 2>/dev/null
544        fi
545
546        sleep 1
547      done
548    fi
549
550    rm -f "$JETTY_PID"
551    rm -f "$JETTY_STATE"
552    echo OK
553
554    ;;
555
556  restart)
557    JETTY_SH=$0
558    > "$JETTY_STATE"
559    if [ ! -f $JETTY_SH ]; then
560      if [ ! -f $JETTY_HOME/bin/jetty.sh ]; then
561        echo "$JETTY_HOME/bin/jetty.sh does not exist."
562        exit 1
563      fi
564      JETTY_SH=$JETTY_HOME/bin/jetty.sh
565    fi
566
567    "$JETTY_SH" stop "$@"
568    "$JETTY_SH" start "$@"
569
570    ;;
571
572  supervise)
573    #
574    # Under control of daemontools supervise monitor which
575    # handles restarts and shutdowns via the svc program.
576    #
577    exec "${RUN_CMD[@]}"
578
579    ;;
580
581  run|demo)
582    echo "Running Jetty: "
583
584    if running "$JETTY_PID"
585    then
586      echo Already Running $(cat "$JETTY_PID")!
587      exit 1
588    fi
589
590    exec "${RUN_CMD[@]}"
591    ;;
592
593  check|status)
594    if running "$JETTY_PID"
595    then
596      echo "Jetty running pid=$(< "$JETTY_PID")"
597    else
598      echo "Jetty NOT running"
599    fi
600    echo
601    dumpEnv
602    echo
603
604    if running "$JETTY_PID"
605    then
606      exit 0
607    fi
608    exit 1
609
610    ;;
611
612  *)
613    usage
614
615    ;;
616esac
617
618exit 0
619