diff --git a/spring-boot-docs/src/main/asciidoc/deployment.adoc b/spring-boot-docs/src/main/asciidoc/deployment.adoc index db5aac5ef5..5ac2493275 100644 --- a/spring-boot-docs/src/main/asciidoc/deployment.adoc +++ b/spring-boot-docs/src/main/asciidoc/deployment.adoc @@ -321,13 +321,13 @@ or `systemd`. -==== Installation as a init.d (system v) service +==== Installation as a init.d (System V) service The default executable script that is embedded into Spring Boot executable jars will act as an `init.d` script when it is symlinked to `/etc/init.d`. The standard `start`, `stop`, `restart` and `status` commands can be used. The script supports the following features: * Starts the services as the user that owns the jar file -* Tracks application PIDs using `/var/run/.pid` +* Tracks application PIDs using `/var/run//.pid` * Writes console logs to `/var/log/.log` Assuming that you have a Spring Boot application installed in `/var/myapp`, to install a @@ -350,6 +350,33 @@ if you use Debian: $ update-rc.d myapp defaults ---- +=== Running a JAR as a regular (not service) script + +The script accepts the following parameters as environment variables, so you can change the +default behaviour in a script or on the command line: + +* `MODE` - the "mode" of operation. The default depends on the way the jar was built, but +will usually be "auto" (meaning it tries to guess if it is an init script by checking if +it is a symlink in a directory called "init.d"). You can explicitly set it to "service" +so that the "stop|start|status|restart" commands work, or to "run" if you just want to +run the script and not in the background. + +* `PID_FOLDER` - the root name of the pid folder (`/var/run` by default). + +* `LOG_FOLDER` - the name of the folder to put log files in (`/var/log` by default). + +* `APP_NAME` - the name of the app. If the jar is run from a symlink the script guesses the +app name, but if it is not a symlink, or you want to explicitly set the app name this can be +useful. + +* `JAVA_HOME` - the location of the `java` executable is discovered by using the `PATH` by +default, but you can set it explicitly if there is an executable file at `$JAVA_HOME/bin/java`. + +* `JARFILE` - the explicit location of the jar file, in case the script is being used to launch +a jar that it is not actually embedded in. + +* `DEBUG` - if not empty will set the `-x` flag on the shell process, making it easy to +see the logic in the script. ==== Installation as a systemd service diff --git a/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script b/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script old mode 100644 new mode 100755 index 6da00583dd..3a492fb765 --- a/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script +++ b/spring-boot-tools/spring-boot-loader-tools/src/main/resources/org/springframework/boot/loader/tools/launch.script @@ -9,20 +9,34 @@ # :: Spring Boot Startup Script :: # +[[ -n "$DEBUG" ]] && set -x + WORKING_DIR="$(pwd)" -PID_FOLDER="/var/run" -USER_PID_FOLDER="/tmp" -LOG_FOLDER="/var/log" -USER_LOG_FOLDER="/tmp" +[[ -n "$JARFILE" ]] && jarfile="$JARFILE" +[[ -n "$APP_NAME" ]] && identity="$APP_NAME" +[[ -z "$PID_FOLDER" ]] && PID_FOLDER="/var/run" +[[ -z "$LOG_FOLDER" ]] && LOG_FOLDER="/var/log" +! [[ -x "$PID_FOLDER" ]] && PID_FOLDER="/tmp" +! [[ -x "$LOG_FOLDER" ]] && LOG_FOLDER="/tmp" # Setup defaults -[[ -z "$mode" ]] && mode="{{mode:auto}}" # modes are "auto", "service" or "run" +[[ -z "$MODE" ]] && MODE="{{mode:auto}}" # modes are "auto", "service" or "run" # ANSI Colors echoRed() { echo $'\e[0;31m'$1$'\e[0m'; } echoGreen() { echo $'\e[0;32m'$1$'\e[0m'; } echoYellow() { echo $'\e[0;33m'$1$'\e[0m'; } +# Utility functions +checkPermissions() { + touch "$pid_file" &> /dev/null || { echoRed "Operation not permitted (cannot access pid file)"; exit 1; } + touch "$log_file" &> /dev/null || { echoRed "Operation not permitted (cannot access log file)"; exit 1; } +} + +isRunning() { + ps -p $1 &> /dev/null +} + # Follow symlinks to find the real jar and detect init.d script cd $(dirname "$0") [[ -z "$jarfile" ]] && jarfile=$(pwd)/$(basename "$0") @@ -36,36 +50,36 @@ cd "$WORKING_DIR" # Determine the script mode action="run" -if [[ "$mode" == "auto" && -n "$init_script" ]] || [[ "$mode" == "service" ]]; then +if [[ "$MODE" == "auto" && -n "$init_script" ]] || [[ "$MODE" == "service" ]]; then action="$1" shift fi # Create an identity for log/pid files -if [[ -n "$init_script" ]]; then - identity="${init_script}" -else - jar_folder=$(dirname "$jarfile") - identity=$(basename "${jarfile%.*}")_${jar_folder//\//} +if [[ -z "$identity" ]]; then + if [[ -n "$init_script" ]]; then + identity="${init_script}" + else + jar_folder=$(dirname "$jarfile") + identity=$(basename "${jarfile%.*}")_${jar_folder//\//} + fi fi # Build the pid and log filenames -if [[ -n "$init_script" ]]; then - pid_file="$PID_FOLDER/${identity}/${identity}.pid" - log_file="$LOG_FOLDER/${identity}.log" -else - pid_file="$USER_PID_FOLDER/${identity}.pid" - log_file="$USER_LOG_FOLDER/${identity}.log" +if [[ "$identity" == "$init_script" ]] || [[ "$identity" == "$APP_NAME" ]]; then + PID_FOLDER="$PID_FOLDER/${identity}" fi +pid_file="$PID_FOLDER/${identity}.pid" +log_file="$LOG_FOLDER/${identity}.log" -# Determine the user to run as +# Determine the user to run as if we are root [[ $(id -u) == "0" ]] && run_user=$(ls -ld "$jarfile" | awk '{print $3}') # Find Java -if type -p java 2>&1> /dev/null; then - javaexe=java -elif [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then +if [[ -n "$JAVA_HOME" ]] && [[ -x "$JAVA_HOME/bin/java" ]]; then javaexe="$JAVA_HOME/bin/java" +elif type -p java 2>&1> /dev/null; then + javaexe=java elif [[ -x "/usr/bin/java" ]]; then javaexe="/usr/bin/java" else @@ -76,16 +90,6 @@ fi # Build actual command to execute command="$javaexe -jar -Dsun.misc.URLClassPath.disableJarChecking=true $jarfile $@" -# Utility functions -checkPermissions() { - touch "$pid_file" &> /dev/null || { echoRed "Operation not permitted (cannot access pid file)"; exit 1; } - touch "$log_file" &> /dev/null || { echoRed "Operation not permitted (cannot access log file)"; exit 1; } -} - -isRunning() { - ps -p $1 &> /dev/null -} - # Action functions start() { if [[ -f "$pid_file" ]]; then @@ -94,9 +98,9 @@ start() { fi pushd $(dirname "$jarfile") > /dev/null if [[ -n "$run_user" ]]; then - mkdir "$PID_FOLDER/${identity}" &> /dev/null + mkdir "$PID_FOLDER" &> /dev/null checkPermissions - chown "$run_user" "$PID_FOLDER/${identity}" + chown "$run_user" "$PID_FOLDER" chown "$run_user" "$pid_file" chown "$run_user" "$log_file" su -c "$command &> \"$log_file\" & echo \$!" $run_user > "$pid_file" @@ -115,6 +119,7 @@ start() { stop() { [[ -f $pid_file ]] || { echoRed "Not running (pidfile not found)"; exit 1; } pid=$(cat "$pid_file") + rm -f "$pid_file" isRunning $pid || { echoRed "Not running (process ${pid} not found)"; exit 1; } kill -HUP $pid &> /dev/null || { echoRed "Unable to kill process ${pid}"; exit 1; } for i in $(seq 1 20); do