首先,先講講我的需求,我的需求如下
- Web Application的版本必需能夠簡單被管理,要能簡單的就知道目前安裝的版本,並且輕鬆的昇級到新版
- Web Application被佈建時,要連Web Container及設定擋包在一起
- Debian Box開關機時,要能自動開關Web Container
這些需求,我是靠 unix-maven-plugin ,幫我把我的 web application 包成一個 .deb 來做到的,包成 .deb 的好處是,在 debian 上可以簡單的安裝,若是公司有架 debian package repository, 那麼,打個 apt-get install
由於 unix-maven-plugin 已被原作者遺棄,所以需要從 github下載並安裝後人修改過的版本。
然後依附錄的方式,增修你的設定檔,需要增修的檔案有
- pom.xml: 加入 unix-maven-plugin 及服務的名稱及PORT
- src/main/unix/resources/default/${service.user} : 給 jetty 用的 default 設定值,在這邊你可以修改 JAVA_OPTIONS 及 NO_START
- src/main/unix/resources/etc/jetty.conf
- src/main/unix/resources/etc/start.conf
- src/main/unix/resources/scripts/${service.user} : 給 debian 用的 init script
- src/main/unix/resources/scripts/post-install post-remove pre-install pre-remove : debian 在安裝及昇級 .deb 時會跑的 script
將這些檔案設定好後,在 debian 的機器上打 mvn package deploy ,就可以自動生成 .deb 的檔案,並且上傳到你的 maven repository 上去,如果貴公司有架 debian package repository 的話,還可以加一段程式碼把 .deb 傳到 debian package repository 去。
接著,打 dpkg -i xxxx.deb 就可以把你的 web application 當成一個 debian service 安裝到你的 debain machine 上去。
查詢目前安裝的板本則是打 dpkg -l xxxx 即可
||/ Name Version Description +++-==============-==============-============================================ ii backend 1.2.0-20120327.143115 backend
附錄
把底下的這段,加入你的 pom.xml
4.0.0 com.locadz backend war backend 1.2.0-SNAPSHOT backend 1.0-alpha-6.1 7.4.5.v20110725 Locadz Backend /var/lib/bluetang/locadz-backend locadz-backend 9080 debian-package unix linux maven-resources-plugin 2.5 copy-resources process-resources copy-resources ${basedir}/target src/main/unix unix **/* true org.mortbay.jetty.toolchain unix-maven-plugin ${version.maven.unix.plugin} true package package-deb-attached true yho@bluetangstudio.com yho@bluetangstudio.com ${service.user} adm ${service.user} adm bluetang extra org.eclipse.jetty:jetty-distribution:zip ${service.home} /jetty-distribution-${version.jetty}(.*) $1 */contexts/** */contexts-available/** */webapps/** */javadoc/** */LICENSES/** */logs/** **/win32/** ${project.build.directory}/${project.build.finalName}.${project.packaging} ${service.home}/webapps/ROOT.war ${basedir}/target/unix/resources/default/${service.user} /etc/default ${basedir}/target/unix/resources/etc /etc/bluetang/${service.user} ${basedir}/target/unix/scripts/${service.user} /etc/init.d 0754 ${service.user} admin org.eclipse.jetty jetty-distribution ${version.jetty} zip * *
然後把下面這塊存成 src/main/unix/resources/default/${service.user}
# Defaults for jetty see /etc/${service.user}/jetty for more # change to 0 to allow Jetty to start NO_START=0 # change to 'no' or uncomment to use the default setting in /etc/default/rcS VERBOSE=yes # Run Jetty as this user ID (default: jetty) # Set this to an empty string to prevent Jetty from starting automatically JETTY_USER=${service.user} # Listen to connections from this network host # Use 0.0.0.0 as host to accept all connections. # Uncomment to restrict access to localhost #JETTY_HOST=$(uname -n) JETTY_HOST=0.0.0.0 # The network port used by Jetty JETTY_PORT=${service.port} # Timeout in seconds for the shutdown of all webapps #JETTY_SHUTDOWN=30 # Additional arguments to pass to Jetty #JETTY_ARGS= # Extra options to pass to the JVM JAVA_OPTIONS="-Xmx256m -Djava.awt.headless=true -Duser.timezone=UTC" # Home of Java installation. #JAVA_HOME= # The first existing directory is used for JAVA_HOME (if JAVA_HOME is not # defined in /etc/default/jetty). Should contain a list of space separated directories. #JDK_DIRS="/usr/lib/jvm/default-java /usr/lib/jvm/java-6-sun" # Java compiler to use for translating JavaServer Pages (JSPs). You can use all # compilers that are accepted by Ant's build.compiler property. #JSP_COMPILER=jikes # Jetty uses a directory to store temporary files like unpacked webapps JETTY_TMP=/var/cache/bluetang/jetty # Jetty uses a config file to setup its boot classpath JETTY_START_CONFIG=/etc/bluetang/${service.user}/start.config # Default for number of days to keep old log files in /var/log/jetty/ #LOGFILE_DAYS=14
然後把下面這塊存成 src/main/unix/resources/ect/jetty.conf
# list of jetty configuration and property files /var/lib/bluetang/${service.user}/etc/jetty-logging.xml
然後把下面這塊存成 src/main/unix/resources/etc/start.conf
# This file controls what file are to be put on classpath or command line. # # Format is as follows: # Each line contains entry for one JAR file. # Format of line: # # SUBJECT [ [!] CONDITION [AND|OR] ]* # # where SUBJECT: # ends with ".class" is the Main class to run. # ends with ".xml" is a configuration file for the command line # ends with "/" is a directory from which to add all jar and zip files. # ends with "/*" is a directory from which to add all unconsidered jar and zip files. # ends with "/**" is a directory from which to recursively add all unconsidered jar and zip files. # Containing = are used to assign system properties. # all other subjects are treated as files to be added to the classpath. # # Subjects may include system properties with $(propertyname) syntax. # # Files starting with "/" are considered absolute, all others are relative to # the home directory. # # CONDITION is one of: # always # never # available classname # true if class on classpath # property name # true of set # java OPERATOR version # java version compared to literal # nargs OPERATOR number # number of command line args compared to literal # OPERATOR := one of "<",">","<=",">=","==","!=" # # CONDITIONS can be combined with AND OR or !, with AND being the assume # operator for a list of CONDITIONS. # Classpath operations are evaluated on the fly, so once a class or jar is # added to the classpath, subsequent available conditions will see that class. # $(jetty.class.path) always $(jetty.lib)/** exists $(jetty.lib) jetty.home=/var/lib/bluetang/${service.user} always # The main class to run org.mortbay.xml.XmlConfiguration.class # The default configuration files $(jetty.home)/etc/jetty.xml nargs == 0 /usr/share/java/servlet-api-2.5.jar /usr/share/java/slf4j-api.jar # Optional stuff for libjetty-extra-java /usr/share/java/gnumail.jar /usr/share/java/activation.jar /usr/share/java/ant.jar # Set the jetty classpath /usr/share/jetty/lib/** # Add a resources directory if it is there $(jetty.home)/resources/
然後把下面這塊存成 src/main/unix/scripts/${service.user}
#!/bin/bash ### BEGIN INIT INFO # Provides: ${service.user} # Required-Start: # Required-Stop: # Default-Start: 2 3 4 5 # Default-Stop: 0 1 6 # Short-Description: Start daemon at boot time # Description: Enable service provided by daemon. ### END INIT INFO # # Startup script for jetty under *nix systems (it works under NT/cygwin too). # # Configuration files # # /etc/default/${service.user} # If it exists, this is read at the start of script. It may perform any # sequence of shell commands, like setting relevant environment variables. # # /etc/bluetang/${service.user}/jetty.conf # If found, and no configurations were given on the command line, # the file will be used as this script's configuration. # Each line in the file may contain: # - A comment denoted by the pound (#) sign as first non-blank character. # - The path to a regular file, which will be passed to jetty as a # config.xml file. # - The path to a directory. Each *.xml file in the directory will be # passed to jetty as a config.xml file. # # The files will be checked for existence before being passed to jetty. # # $JETTY_HOME/etc/jetty.xml # If found, used as this script's configuration file, but only if # /etc/bluetang/${service.user}/jetty.conf was not present. See above. # # Configuration variables # # JAVA # Command to invoke Java. If not set, java (from the PATH) will be used. # # JAVA_OPTIONS # Extra options to pass to the JVM # # JETTY_HOME # Where Jetty is installed. If not set, the script will try go # guess it by first looking at the invocation path for the script, # and then by looking in standard locations as $HOME/opt/jetty # and /opt/jetty. The java system property "jetty.home" will be # set to this value for use by configure.xml files, f.e.: # #然後把下面這塊存成 src/main/unix/scripts/post-install,並修改 USER=locadz-backend 這一行成跟你 ${service.user} 一樣的值# # JETTY_PORT # Override the default port for Jetty servers. If not set then the # default value in the xml configuration file will be used. The java # system property "jetty.port" will be set to this value for use in # configure.xml files. For example, the following idiom is widely # used in the demo config files to respect this property in Listener # configuration elements: # # /webapps/jetty.war # # Note: that the config file could ignore this property simply by saying: # # 8080 # # JETTY_RUN # Where the jetty.pid file should be stored. It defaults to the # first available of /var/run, /usr/var/run, and /tmp if not set. # # JETTY_PID # The Jetty PID file, defaults to $JETTY_RUN/jetty.pid # # JETTY_ARGS # The default arguments to pass to jetty. # # JETTY_USER # if set, then used as a username to run the server as # JETTY_HOME=${service.home} JETTY_USER=${service.user} JETTY_PID=$JETTY_RUN/${service.user}.pid usage() { echo "Usage: ${0##*/} [-d] {start|stop|run|restart|check|supervise} [ CONFIGS ... ] " exit 1 } [ $# -gt 0 ] || usage ################################################## # Some utility functions ################################################## findDirectory() { local L OP=$1 shift for L in "$@"; do [ "$OP" "$L" ] || continue printf %s "$L" break done } running() { local PID=$(cat "$1" 2>/dev/null) || return 1 kill -0 "$PID" 2>/dev/null } readConfig() { (( DEBUG )) && echo "Reading $1.." source "$1" } ################################################## # Get the action & configs ################################################## CONFIGS=() NO_START=0 DEBUG=0 while [[ $1 = -* ]]; do case $1 in -d) DEBUG=1 ;; esac shift done ACTION=$1 shift ################################################## # See if there's a default configuration file ################################################## if [ -f /etc/default/${service.user} ] ; then . /etc/default/${service.user} fi ################################################## # Set tmp if not already set. ################################################## TMPDIR=${TMPDIR:-/tmp} ################################################## # Jetty's hallmark ################################################## JETTY_INSTALL_TRACE_FILE="etc/jetty.xml" ################################################## # Try to determine JETTY_HOME if not set ################################################## if [ -z "$JETTY_HOME" ] then JETTY_SH=$0 case "$JETTY_SH" in /*) ;; ./*) ;; *) JETTY_SH=./$JETTY_SH ;; esac JETTY_HOME=${JETTY_SH%/*/*} if [ ! -f "${JETTY_SH%/*/*}/$JETTY_INSTALL_TRACE_FILE" ] then JETTY_HOME= fi fi ################################################## # if no JETTY_HOME, search likely locations. ################################################## if [ -z "$JETTY_HOME" ] ; then STANDARD_LOCATIONS=( "/usr/share" "/usr/share/java" "${HOME}" "${HOME}/src" "${HOME}/opt" "/opt" "/java" "/usr/local" "/usr/local/share" "/usr/local/share/java" "/home" ) JETTY_DIR_NAMES=( "jetty-7" "jetty7" "jetty-7.*" "jetty" "Jetty-7" "Jetty7" "Jetty-7.*" "Jetty" ) for L in "${STANDARD_LOCATIONS[@]}" do for N in "${JETTY_DIR_NAMES[@]}" do POSSIBLE_JETTY_HOME=("$L/"$N) if [ ! -d "$POSSIBLE_JETTY_HOME" ] then # Not a directory. skip. unset POSSIBLE_JETTY_HOME elif [ ! -f "$POSSIBLE_JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ] then # Trace file not found. skip. unset POSSIBLE_JETTY_HOME else # Good hit, Use it JETTY_HOME=$POSSIBLE_JETTY_HOME # Break out of JETTY_DIR_NAMES loop break fi done if [ -n "$POSSIBLE_JETTY_HOME" ] then # We have found our JETTY_HOME # Break out of STANDARD_LOCATIONS loop break fi done fi ################################################## # No JETTY_HOME yet? We're out of luck! ################################################## if [ -z "$JETTY_HOME" ]; then echo "** ERROR: JETTY_HOME not set, you need to set it or install in a standard location" exit 1 fi cd "$JETTY_HOME" JETTY_HOME=$PWD ##################################################### # Check that jetty is where we think it is ##################################################### if [ ! -r "$JETTY_HOME/$JETTY_INSTALL_TRACE_FILE" ] then echo "** ERROR: Oops! Jetty doesn't appear to be installed in $JETTY_HOME" echo "** ERROR: $JETTY_HOME/$JETTY_INSTALL_TRACE_FILE is not readable!" exit 1 fi ################################################## # Try to find this script's configuration file, # but only if no configurations were given on the # command line. ################################################## if [ -z "$JETTY_CONF" ] then if [ -f /etc/bluetang/${service.user}/jetty.conf ] then JETTY_CONF=/etc/bluetang/${service.user}/jetty.conf elif [ -f "${JETTY_HOME}/etc/jetty.conf" ] then JETTY_CONF="${JETTY_HOME}/etc/jetty.conf" fi fi ################################################## # Get the list of config.xml files from jetty.conf ################################################## if [ -z "$CONFIGS" ] && [ -f "$JETTY_CONF" ] && [ -r "$JETTY_CONF" ] then while read -r CONF do if expr "$CONF" : '#' >/dev/null ; then continue fi if [ -d "$CONF" ] then # assume it's a directory with configure.xml files # for example: /etc/jetty.d/ # sort the files before adding them to the list of CONFIGS for file in "$CONF/"*.xml do if [ -r "$FILE" ] && [ -f "$FILE" ] then CONFIGS+=("$FILE") else echo "** WARNING: Cannot read '$FILE' specified in '$JETTY_CONF'" fi done else # assume it's a command line parameter (let start.jar deal with its validity) CONFIGS+=("$CONF") fi done < "$JETTY_CONF" fi ##################################################### # Find a location for the pid file ##################################################### if [ -z "$JETTY_RUN" ] then JETTY_RUN=$(findDirectory -w /var/run /usr/var/run /tmp) fi ##################################################### # Find a PID for the pid file ##################################################### if [ -z "$JETTY_PID" ] then JETTY_PID="$JETTY_RUN/jetty.pid" fi ################################################## # Setup JAVA if unset ################################################## if [ -z "$JAVA" ] then JAVA=$(which java) fi if [ -z "$JAVA" ] then echo "Cannot find a Java JDK. Please set either set JAVA or put java (>=1.5) in your PATH." 2>&2 exit 1 fi ##################################################### # See if JETTY_PORT is defined ##################################################### if [ "$JETTY_PORT" ] then JAVA_OPTIONS+=("-Djetty.port=$JETTY_PORT") fi ##################################################### # See if JETTY_LOGS is defined ##################################################### if [ "$JETTY_LOGS" ] then JAVA_OPTIONS+=("-Djetty.logs=$JETTY_LOGS") fi ##################################################### # Are we running on Windows? Could be, with Cygwin/NT. ##################################################### case "`uname`" in CYGWIN*) PATH_SEPARATOR=";";; *) PATH_SEPARATOR=":";; esac ##################################################### # Add jetty properties to Java VM options. ##################################################### JAVA_OPTIONS+=("-Djetty.home=$JETTY_HOME" "-Djava.io.tmpdir=$TMPDIR") [ -f "$JETTY_HOME/etc/start.config" ] && JAVA_OPTIONS=("-DSTART=$JETTY_HOME/etc/start.config" "${JAVA_OPTIONS[@]}") ##################################################### # This is how the Jetty server will be started ##################################################### JETTY_START=$JETTY_HOME/start.jar [ ! -f "$JETTY_START" ] && JETTY_START=$JETTY_HOME/lib/start.jar START_INI=$(dirname $JETTY_START)/start.ini [ -r "$START_INI" ] || START_INI="" RUN_ARGS=(${JAVA_OPTIONS[@]} -jar "$JETTY_START" $JETTY_ARGS "${CONFIGS[@]}") RUN_CMD=("$JAVA" ${RUN_ARGS[@]}) ##################################################### # Comment these out after you're happy with what # the script is doing. ##################################################### if (( DEBUG )) then echo "JETTY_HOME = $JETTY_HOME" echo "JETTY_CONF = $JETTY_CONF" echo "JETTY_RUN = $JETTY_RUN" echo "JETTY_PID = $JETTY_PID" echo "JETTY_ARGS = $JETTY_ARGS" echo "CONFIGS = ${CONFIGS[*]}" echo "JAVA_OPTIONS = ${JAVA_OPTIONS[*]}" echo "JAVA = $JAVA" echo "RUN_CMD = ${RUN_CMD}" fi ################################################## # Do the action ################################################## case "$ACTION" in start) echo -n "Starting ${service.name}: " if (( NO_START )); then echo "Not starting ${service.user} - NO_START=1"; exit fi if type start-stop-daemon > /dev/null 2>&1 then unset CH_USER if [ -n "$JETTY_USER" ] then CH_USER="-c$JETTY_USER" fi if start-stop-daemon -S -p"$JETTY_PID" $CH_USER -d"$JETTY_HOME" -b -m -a "$JAVA" -- "${RUN_ARGS[@]}" --daemon then sleep 1 if running "$JETTY_PID" then echo "OK" else echo "FAILED" fi fi else if [ -f "$JETTY_PID" ] then if running $JETTY_PID then echo "Already Running!" exit 1 else # dead pid file - remove rm -f "$JETTY_PID" fi fi if [ "$JETTY_USER" ] then touch "$JETTY_PID" chown "$JETTY_USER" "$JETTY_PID" # FIXME: Broken solution: wordsplitting, pathname expansion, arbitrary command execution, etc. su - "$JETTY_USER" -c " ${RUN_CMD[*]} --daemon & disown \$! echo \$! > '$JETTY_PID'" else "${RUN_CMD[@]}" & disown $! echo $! > "$JETTY_PID" fi echo "STARTED ${service.name} `date`" fi ;; stop) echo -n "Stopping ${service.name}: " if type start-stop-daemon > /dev/null 2>&1; then start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s HUP TIMEOUT=30 while running "$JETTY_PID"; do if (( TIMEOUT-- == 0 )); then start-stop-daemon -K -p"$JETTY_PID" -d"$JETTY_HOME" -a "$JAVA" -s KILL fi sleep 1 done rm -f "$JETTY_PID" echo OK else PID=$(cat "$JETTY_PID" 2>/dev/null) kill "$PID" 2>/dev/null TIMEOUT=30 while running $JETTY_PID; do if (( TIMEOUT-- == 0 )); then kill -KILL "$PID" 2>/dev/null fi sleep 1 done rm -f "$JETTY_PID" echo OK fi ;; restart) JETTY_SH=$0 if [ ! -f $JETTY_SH ]; then if [ ! -f $JETTY_HOME/bin/jetty.sh ]; then echo "$JETTY_HOME/bin/jetty.sh does not exist." exit 1 fi JETTY_SH=$JETTY_HOME/bin/jetty.sh fi "$JETTY_SH" stop "$@" "$JETTY_SH" start "$@" ;; supervise) # # Under control of daemontools supervise monitor which # handles restarts and shutdowns via the svc program. # exec "${RUN_CMD[@]}" ;; run|demo) echo "Running Jetty: " if [ -f "$JETTY_PID" ] then if running "$JETTY_PID" then echo "Already Running!" exit 1 else # dead pid file - remove rm -f "$JETTY_PID" fi fi exec "${RUN_CMD[@]}" ;; check) echo "Checking arguments to Jetty: " echo "JETTY_HOME = $JETTY_HOME" echo "JETTY_CONF = $JETTY_CONF" echo "JETTY_RUN = $JETTY_RUN" echo "JETTY_PID = $JETTY_PID" echo "JETTY_PORT = $JETTY_PORT" echo "JETTY_LOGS = $JETTY_LOGS" echo "START_INI = $START_INI" echo "CONFIGS = ${CONFIGS[*]}" echo "JAVA_OPTIONS = ${JAVA_OPTIONS[*]}" echo "JAVA = $JAVA" echo "CLASSPATH = $CLASSPATH" echo "RUN_CMD = ${RUN_CMD[*]}" echo if [ -f "$JETTY_RUN/jetty.pid" ] then echo "Jetty running pid=$(< "$JETTY_RUN/jetty.pid")" exit 0 fi exit 1 ;; *) usage ;; esac exit 0
#!/bin/sh set -e USER=locadz-backend case "$1" in configure) if ! id $USER > /dev/null 2>&1 ; then adduser --system --home /var/lib/bluetang/$USER --no-create-home \ --group --disabled-password --shell /bin/false \ $USER fi if [ ! -e /var/log/bluetang ] then mkdir -p /var/log/bluetang fi if [ ! -e /var/log/bluetang/$USER/ ] then ln -s /var/lib/bluetang/$USER/logs /var/log/bluetang/$USER fi if [ ! -e /var/cache/bluetang/$USER ] then mkdir -p /var/cache/bluetang/$USER fi chown -R $USER:adm /var/cache/bluetang/$USER /var/log/bluetang/$USER /var/lib/bluetang/$USER chmod 0744 /etc/init.d/$USER update-rc.d $USER defaults ;; abort-upgrade|abort-remove|abort-deconfigure) ;; *) echo "$0 called with unknown argument \`$1'" >&2 exit 1 ;; esac然後把下面這塊存成 src/main/unix/scripts/post-remove,並修改 USER=locadz-backend 這一行成跟你 ${service.user} 一樣的值
#!/bin/sh set -e USER=locadz-backend #DEBHELPER# # Remove cached files rm -rf /var/cache/blutang/$USER/* case "$1" in remove) # Remove ROOT webapp if not modified RWLOC="/var/lib/bluetang/$USER/webapps/root" RWFILES="$RWLOC/index.html $RWLOC/jetty_banner.gif" if [ "`(cat $RWFILES | md5sum -) 2>/dev/null | cut -d ' ' -f 1`" \ = "12471c4b3020defb7ebd30ef84c0f9dd" ] ; then rm $RWFILES rmdir --ignore-fail-on-non-empty \ /var/lib/bluetang/$USER/webapps/root \ /var/lib/bluetang/$USER/webapps \ /var/lib/bluetang/$USER || true fi if [ -d "/var/cache/bluetang/$USER" ] ; then rm -rf /var/cache/bluetang/$USER fi ;; purge) # Remove user/group and log files (don't remove everything under # /var/lib/jetty because there might be user-installed webapps) deluser jetty || true rm -rf /var/log/bluetang/$USER if [ -d "/var/lib/bluetang/$USER" ] ; then rmdir --ignore-fail-on-non-empty /var/lib/bluetang/$USER || true fi rmdir --ignore-fail-on-non-empty /etc/bluetang/$USER/contexts /etc/bluetang/$USER || true ;; remove|upgrade|failed-upgrade|abort-install|abort-upgrade|disappear) # Nothing to do here ;; *) echo "$0 called with unknown argument \`$1'" >&2 exit 1 ;; esac然後把下面這塊存成 src/main/unix/scripts/pre-install,並修改 USER=locadz-backend 這一行成跟你 ${service.user} 一樣的值
#!/bin/sh # # This is the preinst script for the Blue Tang Servers # # Written by Yung-Lin Ho yho@bluetangstudio.com set -e USER=locadz-backend SCRIPT=/etc/init.d/$USER case "$1" in upgrade|remove|purge) $SCRIPT stop ;; install|failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "preinst called with unknown argument \`$1'" >&2 ;; esac exit 0下面這塊存成 src/main/unix/scripts/pre-remove,並修改 USER=locadz-backend 這一行成跟你 ${service.user} 一樣的值
#!/bin/sh # # This is the prerm script for the Blue Tang Servers # # Written by Yung-Lin Ho yho@bluetangstudio.com set -e USER=locadz-backend SCRIPT=/etc/init.d/$USER case "$1" in upgrade) ;; remove|purge) $SCRIPT stop ;; failed-upgrade|abort-install|abort-upgrade|disappear) ;; *) echo "prerm called with unknown argument \`$1'" >&2 ;; esac exit 0
No comments:
Post a Comment