diff --git a/Documentation/config-gerrit.txt b/Documentation/config-gerrit.txt index 76385ef876..700284baaf 100644 --- a/Documentation/config-gerrit.txt +++ b/Documentation/config-gerrit.txt @@ -384,6 +384,50 @@ See link:config-contact.html[Contact Information]. + Shared secret of the web based contact store. + +[[container]]Section container +~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +These settings are applied only if Gerrit is started as the container +process through Gerrit's 'gerrit.sh' rc.d compatible wrapper script. + +[[container.heapLimit]]container.heapLimit:: ++ +Maximum heap size of the Java process running Gerrit, in bytes. +This property is translated into the '-Xmx' flag for the JVM. ++ +Default is platform and JVM specific. ++ +Common unit suffixes of 'k', 'm', or 'g' are supported. + +[[container.javaHome]]container.javaHome:: ++ +Path of the JRE/JDK installation to run Gerrit with. If not set, the +Gerrit startup script will attempt to search your system and guess +a suitable JRE. Overrides the environment variable 'JAVA_HOME'. + +[[container.javaOptions]]container.javaOptions:: ++ +Additional options to pass along to the Java runtime. If multiple +values are configured, they are passed in order on the command line, +separated by spaces. These options are appended onto 'JAVA_OPTIONS'. + +[[container.user]]container.user:: ++ +Login name (or UID) of the operating system user the Gerrit JVM +will execute as. If not set, defaults to the user who launched +the 'gerrit.sh' wrapper script. + +[[container.war]]container.war:: ++ +Path of the JAR file to start daemon execution with. This should +be the path of the local 'gerrit.war' archive. Overrides the +environment variable 'GERRIT_WAR'. ++ +If not set, defaults to '$site_path/bin/gerrit.war', or to +'$HOME/gerrit.war'. + + [[core]]Section core ~~~~~~~~~~~~~~~~~~~~ diff --git a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java index 58b554ee14..c9002a842c 100644 --- a/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java +++ b/gerrit-pgm/src/main/java/com/google/gerrit/pgm/Init.java @@ -14,9 +14,10 @@ package com.google.gerrit.pgm; -import static com.google.gerrit.pgm.util.DataSourceProvider.Type.H2; import static com.google.gerrit.pgm.util.DataSourceProvider.Context.SINGLE_USER; +import static com.google.gerrit.pgm.util.DataSourceProvider.Type.H2; +import com.google.gerrit.main.GerritLauncher; import com.google.gerrit.pgm.util.ConsoleUI; import com.google.gerrit.pgm.util.DataSourceProvider; import com.google.gerrit.pgm.util.ErrorLogFile; @@ -47,8 +48,13 @@ import org.eclipse.jgit.util.SystemReader; import org.kohsuke.args4j.Option; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; import java.io.IOException; +import java.io.InputStream; import java.net.InetAddress; +import java.net.URL; import java.net.UnknownHostException; import java.util.ArrayList; import java.util.Collections; @@ -147,12 +153,14 @@ public class Init extends SiteProgram { private void initSitePath() throws IOException, InterruptedException { final File sitePath = getSitePath(); + final File bin_dir = new File(sitePath, "bin"); final File etc_dir = new File(sitePath, "etc"); final File lib_dir = new File(sitePath, "lib"); final File logs_dir = new File(sitePath, "logs"); final File static_dir = new File(sitePath, "static"); final File cache_dir = new File(sitePath, "cache"); + final File gerrit_sh = new File(bin_dir, "gerrit.sh"); final File gerrit_config = new File(etc_dir, "gerrit.config"); final File secure_config = new File(etc_dir, "secure.config"); final File replication_config = new File(etc_dir, "replication.config"); @@ -179,6 +187,7 @@ public class Init extends SiteProgram { init_database(cfg, sec); init_auth(cfg, sec); init_sendemail(cfg, sec); + init_container(cfg, bin_dir); init_sshd(cfg, sec); init_httpd(cfg, sec); @@ -193,17 +202,22 @@ public class Init extends SiteProgram { } } + bin_dir.mkdir(); etc_dir.mkdir(); lib_dir.mkdir(); logs_dir.mkdir(); static_dir.mkdir(); if (!secure_config.exists()) { - chmod600(secure_config); + chmod(0600, secure_config); } if (!replication_config.exists()) { replication_config.createNewFile(); } + if (!gerrit_sh.exists()) { + extract(gerrit_sh, "WEB-INF/extra/bin/gerrit.sh"); + chmod(0755, gerrit_sh); + } } private void initGit() throws OrmException, IOException { @@ -273,7 +287,7 @@ public class Init extends SiteProgram { throw new IOException("Cannot lock " + path); } try { - chmod600(new File(path.getParentFile(), path.getName() + ".lock")); + chmod(0600, new File(path.getParentFile(), path.getName() + ".lock")); lf.write(out); if (!lf.commit()) { throw new IOException("Cannot commit write to " + path); @@ -283,19 +297,26 @@ public class Init extends SiteProgram { } } - private static void chmod600(final File path) throws IOException { + private static void chmod(final int mode, final File path) throws IOException { if (!path.exists() && !path.createNewFile()) { throw new IOException("Cannot create " + path); } - path.setWritable(false, false /* all */); path.setReadable(false, false /* all */); + path.setWritable(false, false /* all */); path.setExecutable(false, false /* all */); - path.setWritable(true, true /* owner only */); - path.setReadable(true, true /* owner only */); - if (path.isDirectory()) { + path.setReadable((mode & 0400) == 0400, true /* owner only */); + path.setWritable((mode & 0200) == 0200, true /* owner only */); + if (path.isDirectory() || (mode & 0100) == 0100) { path.setExecutable(true, true /* owner only */); } + + if ((mode & 0044) == 0044) { + path.setReadable(true, false /* all */); + } + if ((mode & 0011) == 0011) { + path.setExecutable(true, false /* all */); + } } private void init_gerrit_basepath(final Config cfg) { @@ -452,6 +473,48 @@ public class Init extends SiteProgram { set(sec, "sendemail", "smtpPass", password); } + private void init_container(final Config cfg, final File bin_dir) + throws IOException { + ui.header("Container Process"); + + String javaHome = System.getProperty("java.home"); + if (!ui.yesno("Use %s", javaHome)) { + final String guess = "AUTO SELECT"; + javaHome = ui.readString(guess, "Path of JAVA_HOME"); + if (javaHome == guess) { + javaHome = null; + } + } + set(cfg, "container", "javaHome", javaHome); + + String user = ui.readString(username(), "Local username to run as"); + set(cfg, "container", "user", user); + + File mywar; + try { + mywar = GerritLauncher.getDistributionArchive(); + } catch (FileNotFoundException e) { + System.err.println("warn: Cannot find gerrit.war; skipping java.start"); + mywar = null; + } + if (mywar != null) { + String war = null; + + if (ui.yesno("Run from %s", mywar.getAbsolutePath())) { + war = mywar.getAbsolutePath(); + + } else { + if (!ui.isBatch()) { + System.err.format("Copying gerrit.war to %s", bin_dir); + System.err.println(); + } + copy(new File(bin_dir, "gerrit.war"), new FileInputStream(mywar)); + } + + set(cfg, "container", "war", war); + } + } + private void init_sshd(final Config cfg, final Config sec) throws IOException, InterruptedException { ui.header("SSH Daemon"); @@ -508,7 +571,7 @@ public class Init extends SiteProgram { if (!tmpdir.mkdir()) { throw die("Cannot create directory " + tmpdir); } - chmod600(tmpdir); + chmod(0600, tmpdir); final String keyname = "ssh_host_key"; final File tmpkey = new File(tmpdir, keyname); @@ -520,7 +583,7 @@ public class Init extends SiteProgram { p.setPath(tmpkey.getAbsolutePath()); p.setAlgorithm("RSA"); p.loadKeys(); // forces the key to generate. - chmod600(tmpkey); + chmod(0600, tmpkey); final File key = new File(etc_dir, keyname); if (!tmpkey.renameTo(key)) { @@ -590,7 +653,7 @@ public class Init extends SiteProgram { if (!tmpdir.mkdir()) { throw die("Cannot create directory " + tmpdir); } - chmod600(tmpdir); + chmod(0600, tmpdir); final File tmpstore = new File(tmpdir, "keystore"); Runtime.getRuntime().exec(new String[] {"keytool", // @@ -603,7 +666,7 @@ public class Init extends SiteProgram { "-dname", dname, // "-keypass", ssl_pass, // }).waitFor(); - chmod600(tmpstore); + chmod(0600, tmpstore); final File store = new File(etc_dir, "keystore"); if (!tmpstore.renameTo(store)) { @@ -720,4 +783,33 @@ public class Init extends SiteProgram { System.err.println("warn: Cannot remove " + path); } } + + private static void extract(final File dst, final String path) + throws IOException { + final URL u = GerritLauncher.class.getClassLoader().getResource(path); + if (u == null) { + System.err.println("warn: Cannot read " + path); + return; + } + copy(dst, u.openStream()); + } + + private static void copy(final File dst, final InputStream in) + throws FileNotFoundException, IOException { + try { + dst.getParentFile().mkdirs(); + final FileOutputStream out = new FileOutputStream(dst); + try { + final byte[] buf = new byte[4096]; + int n; + while (0 < (n = in.read(buf))) { + out.write(buf, 0, n); + } + } finally { + out.close(); + } + } finally { + in.close(); + } + } } diff --git a/gerrit-war/src/main/webapp/WEB-INF/extra/bin/gerrit.sh b/gerrit-war/src/main/webapp/WEB-INF/extra/bin/gerrit.sh new file mode 100755 index 0000000000..8320a5fdb8 --- /dev/null +++ b/gerrit-war/src/main/webapp/WEB-INF/extra/bin/gerrit.sh @@ -0,0 +1,494 @@ +#!/bin/sh +# +# Launch Gerrit Code Review as a daemon process. + +# To get the service to restart correctly on reboot, uncomment below (3 lines): +# ======================== +# chkconfig: 3 99 99 +# description: Gerrit Code Review +# processname: gerrit +# ======================== + +# Configuration files: +# +# /etc/default/gerritcodereview +# If it exists, sourced at the start of this script. It may perform any +# sequence of shell commands, like setting relevant environment variables. +# +# The files will be checked for existence before being sourced. + +# Configuration variables. These may be set in /etc/default/gerritcodereview. +# +# GERRIT_SITE +# Path of the Gerrit site to run. $GERRIT_SITE/etc/gerrit.config +# will be used to configure the process. +# +# GERRIT_WAR +# Location of the gerrit.war download that we will execute. Defaults to +# container.war property in $GERRIT_SITE/etc/gerrit.config. +# +# NO_START +# If set to "1" disables Gerrit from starting. + +# Set to 0 if you do not want to use start-stop-daemon (especially on SUSE boxes) +START_STOP_DAEMON=1 + +usage() { + me=`basename "$0"` + echo >&2 "Usage: $me {start|stop|restart|check|run|supervise} [-d site]" + exit 1 +} + +test $# -gt 0 || usage + +################################################## +# Some utility functions +################################################## +running() { + test -f $1 || return 1 + PID=$(cat $1) + ps -p $PID >/dev/null 2>/dev/null || return 1 + return 0 +} + +get_config() { + if test -f "$GERRIT_CONFIG" ; then + if type git >/dev/null 2>&1 ; then + if test "x$1" = x--int ; then + # Git might not be able to expand "8g" properly. If it gives + # us 0 back retry for the raw string and expand ourselves. + # + n=`git config --file "$GERRIT_CONFIG" --int "$2"` + if test x0 = "x$n" ; then + n=`git config --file "$GERRIT_CONFIG" --get "$2"` + case "$n" in + *g) n=`expr ${n%%g} \* 1024`m ;; + *k) n=`expr ${n%%k} \* 1024` ;; + *) : ;; + esac + fi + echo "$n" + else + git config --file "$GERRIT_CONFIG" $1 "$2" + fi + + else + # This is a very crude parser for the git configuration file. + # Its not perfect but it can at least pull some basic values + # from a reasonably standard format. + # + s=`echo "$2" | cut -d. -f1` + k=`echo "$2" | cut -d. -f2` + i=0 + while read n ; do + case "$n" in + '['$s']') i=1 ;; + '['*']' ) i=0 ;; + esac + test $i || continue + + case "$n" in + *[' ']$k[' ']*=*) : ;; + [' ']$k=*) : ;; + $k[' ']*=*) : ;; + $k=*) : ;; + *) continue ;; + esac + + n=${n#*=} + if test "x$1" = x--int ; then + case "$n" in + *g) n=`expr ${n%%g} \* 1024`m ;; + *k) n=`expr ${n%%k} \* 1024` ;; + *) : ;; + esac + fi + echo "$n" + done <"$GERRIT_CONFIG" + fi + fi +} + +################################################## +# Get the action and options +################################################## + +ACTION=$1 +shift + +while test $# -gt 0 ; do + case "$1" in + -d|--site-path) + shift + GERRIT_SITE=$1 + shift + ;; + -d=*) + GERRIT_SITE=${1##-d=} + shift + ;; + --site-path=*) + GERRIT_SITE=${1##--site-path=} + shift + ;; + + *) + usage + esac +done + +NO_START=0 + +################################################## +# See if there's a default configuration file +################################################## +if test -f /etc/default/gerritcodereview ; then + . /etc/default/gerritcodereview +fi + +################################################## +# Set tmp if not already set. +################################################## +if test -z "$TMP" ; then + TMP=/tmp +fi +TMPJ=$TMP/j$$ + +################################################## +# Reasonable guess marker for a Gerrit site path. +################################################## +GERRIT_INSTALL_TRACE_FILE=etc/gerrit.config + +################################################## +# Try to determine GERRIT_SITE if not set +################################################## +if test -z "$GERRIT_SITE" ; then + GERRIT_SITE_1=`dirname "$0"` + GERRIT_SITE_1=`dirname "$GERRIT_SITE_1"` + if test -f "${GERRIT_SITE_1}/${GERRIT_INSTALL_TRACE_FILE}" ; then + GERRIT_SITE=${GERRIT_SITE_1} + fi +fi + +################################################## +# No GERRIT_SITE yet? We're out of luck! +################################################## +if test -z "$GERRIT_SITE" ; then + echo >&2 "** ERROR: GERRIT_SITE not set" + exit 1 +fi + +if cd "$GERRIT_SITE" ; then + GERRIT_SITE=`pwd` +else + echo >&2 "** ERROR: Gerrit site $GERRIT_SITE not found" + exit 1 +fi + +##################################################### +# Check that Gerrit is where we think it is +##################################################### +GERRIT_CONFIG="$GERRIT_SITE/$GERRIT_INSTALL_TRACE_FILE" +test -e "$GERRIT_CONFIG" || { + echo "** ERROR: Gerrit is not initialized in $GERRIT_SITE" + exit 1 +} +test -r "$GERRIT_CONFIG" || { + echo "** ERROR: $GERRIT_CONFIG is not readable!" + exit 1 +} + +GERRIT_PID="$GERRIT_SITE/logs/gerrit.pid" + +################################################## +# Check for JAVA_HOME +################################################## +if test -z "$JAVA_HOME" ; then + JAVA_HOME=`get_config --get container.javaHome` +fi +if test -z "$JAVA_HOME" ; then + # If a java runtime is not defined, search the following + # directories for a JVM and sort by version. Use the highest + # version number. + + JAVA_LOCATIONS="\ + /usr/java \ + /usr/bin \ + /usr/local/bin \ + /usr/local/java \ + /usr/local/jdk \ + /usr/local/jre \ + /usr/lib/jvm \ + /opt/java \ + /opt/jdk \ + /opt/jre \ + " + for N in java jdk jre ; do + for L in $JAVA_LOCATIONS ; do + test -d "$L" || continue + find $L -name "$N" ! -type d | grep -v threads | while read J ; do + test -x "$J" || continue + VERSION=`eval "$J" -version 2>&1` + test $? = 0 || continue + VERSION=`expr "$VERSION" : '.*"\(1.[0-9\.]*\)["_]'` + test -z "$VERSION" && continue + expr "$VERSION" \< 1.2 >/dev/null && continue + echo "$VERSION:$J" + done + done + done | sort | tail -1 >"$TMPJ" + JAVA=`cat "$TMPJ" | cut -d: -f2` + JVERSION=`cat "$TMPJ" | cut -d: -f1` + rm -f "$TMPJ" + + JAVA_HOME=`dirname "$JAVA"` + while test -n "$JAVA_HOME" \ + -a "$JAVA_HOME" != "/" \ + -a ! -f "$JAVA_HOME/lib/tools.jar" ; do + JAVA_HOME=`dirname "$JAVA_HOME"` + done + test -z "$JAVA_HOME" && JAVA_HOME= + + echo "** INFO: Using $JAVA" +fi + +if test -z "$JAVA" -a -n "$JAVA_HOME" ; then + test -x $JAVA_HOME/bin/java -a ! -d $JAVA_HOME/bin/java && JAVA=$JAVA_HOME/bin/java +fi + +if test -z "$JAVA" ; then + echo >&2 "Cannot find a JRE or JDK. Please set JAVA_HOME to a >=1.6 JRE" + exit 1 +fi + +##################################################### +# Add Gerrit properties to Java VM options. +##################################################### + +GERRIT_OPTIONS=`get_config --get-all container.javaOptions` +if test -n "$GERRIT_OPTIONS" ; then + JAVA_OPTIONS="$JAVA_OPTIONS $GERRIT_OPTIONS" +fi + +GERRIT_MEMORY=`get_config --get container.heapLimit` +if test -n "$GERRIT_MEMORY" ; then + JAVA_OPTIONS="$JAVA_OPTIONS -Xmx$GERRIT_MEMORY" +fi + +GERRIT_FDS=`get_config --int core.packedGitOpenFiles` +test -z "$GERRIT_FDS" && GERRIT_FDS=128 +GERRIT_FDS=`expr $GERRIT_FDS + $GERRIT_FDS` + +GERRIT_USER=`get_config --get container.user` + +##################################################### +# Configure sane ulimits for a daemon of our size. +##################################################### + +ulimit -c 0 ; # core file size +ulimit -d unlimited ; # data seg size +ulimit -f unlimited ; # file size +ulimit -m unlimited ; # max memory size +ulimit -n $GERRIT_FDS ; # open files +ulimit -t unlimited ; # cpu time +ulimit -t unlimited ; # virtual memory +ulimit -x unlimited ; # file locks + +##################################################### +# This is how the Gerrit server will be started +##################################################### + +if test -z "$GERRIT_WAR" ; then + GERRIT_WAR=`get_config --get container.war` +fi +if test -z "$GERRIT_WAR" ; then + GERRIT_WAR="$GERRIT_SITE/bin/gerrit.war" + test -f "$GERRIT_WAR" || GERRIT_WAR= +fi +if test -z "$GERRIT_WAR" -a -n "$GERRIT_USER" ; then + for homedirs in /home /Users ; do + if test -d "$homedirs/$GERRIT_USER" ; then + GERRIT_WAR="$homedirs/$GERRIT_USER/gerrit.war" + if test -f "$GERRIT_WAR" ; then + break + else + GERRIT_WAR= + fi + fi + done +fi +if test -z "$GERRIT_WAR" ; then + echo >&2 "** ERROR: Cannot find gerrit.war (try setting gerrit.war)" + exit 1 +fi + +test -z "$GERRIT_USER" && GERRIT_USER=$(whoami) +RUN_ARGS="-jar $GERRIT_WAR daemon -d $GERRIT_SITE" +if test -n "$JAVA_OPTIONS" ; then + RUN_ARGS="$JAVA_OPTIONS $RUN_ARGS" +fi + +if test -x /usr/bin/perl ; then + # If possible, use Perl to mask the name of the process so its + # something specific to us rather than the generic 'java' name. + # + RUN_EXEC=/usr/bin/perl + RUN_Arg1=-e + RUN_Arg2='$x=shift @ARGV;exec $x @ARGV;die $!' + RUN_Arg3="-- $JAVA GerritCodeReview" +else + RUN_EXEC=$JAVA + RUN_Arg1= + RUN_Arg2='-DGerritCodeReview=1' + RUN_Arg3= +fi + +################################################## +# Do the action +################################################## +case "$ACTION" in + start) + echo -n "Starting Gerrit Code Review: " + + if test 1 = "$NO_START" ; then + echo "Not starting gerrit - NO_START=1 in /etc/default/gerrit" + exit 0 + fi + + if test 1 = "$START_STOP_DAEMON" && type start-stop-daemon >/dev/null 2>&1 + then + test $UID = 0 && CH_USER="-c $GERRIT_USER" + if start-stop-daemon -S -b $CH_USER \ + -p "$GERRIT_PID" -m \ + -d "$GERRIT_SITE" \ + -a "$RUN_EXEC" -- $RUN_Arg1 "$RUN_Arg2" $RUN_Arg3 $RUN_ARGS + then + sleep 1 + if running "$GERRIT_PID" ; then + echo OK + else + echo FAILED + fi + fi + else + if test -f "$GERRIT_PID" ; then + if running "$GERRIT_PID" ; then + echo "Already Running!!" + exit 1 + else + rm -f "$GERRIT_PID" + fi + fi + + if test -n "$GERRIT_USER" ; then + touch "$GERRIT_PID" + chown $GERRIT_USER "$GERRIT_PID" + su - $GERRIT_USER -c " + $RUN_EXEC $RUN_Arg1 '$RUN_Arg2' $RUN_Arg3 $RUN_ARGS & ; + PID=\$! ; + disown \$PID ; + echo \$PID >\"$GERRIT_PID\"" + else + $RUN_EXEC $RUN_Arg1 "$RUN_Arg2" $RUN_Arg3 $RUN_ARGS & + PID=$! + disown $PID + echo $PID >"$GERRIT_PID" + fi + + echo "STARTED Gerrit `date`" + fi + ;; + + stop) + echo -n "Stopping Gerrit Code Review: " + + if test 1 = "$START_STOP_DAEMON" && type start-stop-daemon >/dev/null 2>&1 + then + start-stop-daemon -K -p "$GERRIT_PID" -s HUP + sleep 1 + if running "$GERRIT_PID" ; then + sleep 3 + if running "$GERRIT_PID" ; then + sleep 30 + if running "$GERRIT_PID" ; then + start-stop-daemon -K -p "$GERRIT_PID" -s KILL + fi + fi + fi + rm -f "$GERRIT_PID" + echo OK + else + PID=`cat "$GERRIT_PID" 2>/dev/null` + TIMEOUT=30 + while running "$GERRIT_PID" && test $TIMEOUT -gt 0 ; do + kill $PID 2>/dev/null + sleep 1 + let TIMEOUT=$TIMEOUT-1 + done + test $TIMEOUT -gt 0 || kill -9 $PID 2>/dev/null + rm -f "$GERRIT_PID" + echo OK + fi + ;; + + restart) + GERRIT_SH=$0 + if ! test -f "$GERRIT_SH" ; then + echo >&2 "** ERROR: Cannot locate gerrit.sh" + exit 1 + fi + $GERRIT_SH stop $* + sleep 5 + $GERRIT_SH start $* + ;; + + supervise) + # + # Under control of daemontools supervise monitor which + # handles restarts and shutdowns via the svc program. + # + exec "$RUN_EXEC" $RUN_Arg1 "$RUN_Arg2" $RUN_Arg3 $RUN_ARGS + ;; + + run|daemon) + echo "Running Gerrit Code Review:" + + if test -f "$GERRIT_PID" ; then + if running "$GERRIT_PID" ; then + echo "Already Running!!" + exit 1 + else + rm -f "$GERRIT_PID" + fi + fi + + exec "$RUN_EXEC" $RUN_Arg1 "$RUN_Arg2" $RUN_Arg3 $RUN_ARGS --console-log + ;; + + check) + echo "Checking arguments to Gerrit Code Review:" + echo " GERRIT_SITE = $GERRIT_SITE" + echo " GERRIT_CONFIG = $GERRIT_CONFIG" + echo " GERRIT_PID = $GERRIT_PID" + echo " GERRIT_WAR = $GERRIT_WAR" + echo " GERRIT_FDS = $GERRIT_FDS" + echo " GERRIT_USER = $GERRIT_USER" + echo " JAVA = $JAVA" + echo " JAVA_OPTIONS = $JAVA_OPTIONS" + echo " RUN_EXEC = $RUN_EXEC $RUN_Arg1 '$RUN_Arg2' $RUN_Arg3" + echo " RUN_ARGS = $RUN_ARGS" + echo + + if test -f "$GERRIT_PID" ; then + echo "Gerrit running pid="`cat "$GERRIT_PID"` + exit 0 + fi + exit 1 + ;; + + *) + usage + ;; +esac + +exit 0