#!/usr/bin/env bash # Licensed to the Apache Software Foundation (ASF) under one # or more contributor license agreements. See the NOTICE file # distributed with this work for additional information # regarding copyright ownership. The ASF licenses this file # to you under the Apache License, Version 2.0 (the # "License"); you may not use this file except in compliance # with the License. You may obtain a copy of the License at # # http://www.apache.org/licenses/LICENSE-2.0 # # Unless required by applicable law or agreed to in writing, software # distributed under the License is distributed on an "AS IS" BASIS, # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. # See the License for the specific language governing permissions and # limitations under the License. # # ========= # # Startup script for Fuseki under *nix systems (works with cygwin too) # # Configuration # ------------- # Values are loaded from /etc/default/fuseki, if it exists. # The description below cover the default settings if /etc/default/fuseki # does not exist. # # Set DEBUG=1 (see below or set the environment variable) to print the # settings to be used. # # JAVA # Command to invoke Java. If not set, java (from the PATH) will be used. # JAVA_HOME can also be used to set JAVA. # # JAVA_OPTIONS # Extra options to pass to the JVM. # # FUSEKI_HOME # Where Fuseki is installed. If not set, the script will try # to guess it based on the script invokation path. # # FUSEKI_BASE # The root of the runtime area - logs files, system files, local configuration. # Defaults to $FUSEKI_HOME/run. # # FUSEKI_RUN # Where the fuseki.pid file should be stored. It defaults # first available of /var/run, /usr/var/run, $FUSEKI_HOME and /tmp if not set. # # FUSEKI_PID # The FUSEKI PID file, defaults to $FUSEKI_RUN/fuseki.pid # # FUSEKI_ARGS # The arguments to pass to the Fuseki server on the command line. Defaults to: # # if FUSEKI_CONF is not set # --config=$FUSEKI_CONF # if FUSEKI_CONF is set # # FUSEKI_START # Path to the jar file. Defaults to $FUSEKI_HOME/fuseki-server.jar # # FUSEKI_CLASSES # Path to extra jars to add to the class path. Defaults to none # Should be of the form path/class.jar:path/class2.jar # # FUSEKI_CONF # The Fuseki configuration file, usually in RDF Turtle notation. # # FUSEKI_USER # If set, the server will be run as this user # # FUSEKI_LOGS # Directory where logs will be generated. # Fixed as $FUSEKI_BASE/logs. # # FUSEKI_LOGS_STDERROUT # Log file with stderr and stdout log output from Fuseki. # Defaults to $FUSEKI_LOGS/stderrout.log ### BEGIN INIT INFO # Provides: fuseki # Required-Start: $remote_fs $network # Required-Stop: $remote_fs $network # Default-Start: 3 4 5 # Default-Stop: 0 1 2 6 # Short-Description: Start Jena Fuseki at boot time # Description: Jena Fuseki is a service that provides a SPARQL API over HTTP ### END INIT INFO # DEBUG=1 NAME=fuseki if [ -f /etc/default/$NAME ]; then . /etc/default/$NAME fi # simple replacements for LSB daemon logging functions if not defined # Centos 6 has init-functions but not log_daemon_msg/log_begin_msg/log_end_msg # Define simple version - attempt to replace with /lib/lsb/init-functions log_daemon_msg() { echo $1 } log_begin_msg() { echo $1 } log_end_msg() { if [ $1 -eq 0 ]; then echo '[OK]' else echo '[failed]' fi } if [ -f /lib/lsb/init-functions ]; then . /lib/lsb/init-functions fi usage() { echo "Usage: ${0##*/} {start|stop|restart|run|status}" exit 1 } [ $# -gt 0 ] || usage CMD="$1" # Utility functions findDirectory() { local L OP=$1 shift for L in "$@"; do [ "$OP" "$L" ] || continue printf %s "$L" break done } findFile() { local L F=$1 shift for L in "$@"; do [ -f "${L}/${F}" ] || continue printf %s "${L}/${F}" break done } running() { local PID=$(cat "$1" 2>/dev/null) || return 1 ps -p "$PID" >/dev/null 2>&1 } # Are we running in cygwin? cygwin=false case "`uname`" in CYGWIN*) cygwin=true;; esac # Set FUSKEI_HOME to the script invocation directory if it is not specified if [ -z "$FUSEKI_HOME" ] then SCRIPT="$0" # Catch common issue: script has been symlinked if [ -L "$SCRIPT" ] then SCRIPT="$(readlink "$0")" # If link is relative case "$SCRIPT" in /*) ;; # fine *) SCRIPT=$( dirname "$0" )/$SCRIPT;; # fix esac fi # Work out root from script location FUSEKI_HOME="$( cd "$( dirname "$SCRIPT" )" && pwd )" fi # Deal with Cygwin path issues if [ "$cygwin" == "true" ] then FUSEKI_HOME=`cygpath -w "$FUSEKI_HOME"` fi if [ ! -e "$FUSEKI_HOME" ] then log_daemon_msg "FUSEKI_HOME '$FUSEKI_HOME' does not exist" 1>&2 exit 1 fi # Set FUSEKI_BASE if [ -z "$FUSEKI_BASE" ] then #FUSEKI_BASE="/etc/fuseki" FUSEKI_BASE="$FUSEKI_HOME/run" # Autocreate FUSEKI_BASE if defaulting to FUSEKI_HOME/run (simple deployment) if [ ! -e "$FUSEKI_BASE" ] then log_daemon_msg "Creating '$FUSEKI_BASE'" if [ "$cygwin" == "true" ] then FUSEKI_BASE=`cygpath -w "$FUSEKI_BASE"` fi mkdir "$FUSEKI_BASE" fi fi if [ "$cygwin" == "true" ] then FUSEKI_BASE=`cygpath -w "$FUSEKI_BASE"` fi if [ ! -e "$FUSEKI_BASE" -o ! -d "$FUSEKI_BASE" ] then log_daemon_msg "FUSEKI_BASE '$FUSEKI_BASE' does not exist or is not a directory" 1>&2 exit 1 fi if [ ! -w "$FUSEKI_BASE" ] then log_daemon_msg "FUSEKI_BASE '$FUSEKI_BASE' is not writable." 1>&2 exit 1 fi # Find a location for the pid file if [ -z "$FUSEKI_RUN" ] then FUSEKI_RUN=$(findDirectory -w /var/run /usr/var/run $FUSEKI_HOME /tmp) fi # Get PID file name if [ -z "$FUSEKI_PID" ] then FUSEKI_PID="$FUSEKI_RUN/fuseki.pid" fi # Log directory if [ -n "$FUSEKI_LOGS" ] then log_daemon_message "FUSEKI_LOGS can not be set externally - ignored" 1>&2 fi FUSEKI_LOGS="$FUSEKI_BASE/logs" # Stderr and stdout log if [ -z "$FUSEKI_LOGS_STDERROUT" ] then FUSEKI_LOGS_STDERROUT="$FUSEKI_LOGS/stderrout.log" fi # Set up JAVA if not set if [ -z "$JAVA" ] then if [ -z "$JAVA_HOME" ] then JAVA=$(which java) else JAVA=$JAVA_HOME/bin/java fi fi if [ -z "$JAVA" ] then ( echo "Cannot find a Java JDK." echo "Please set either set JAVA or JAVA_HOME and put java (>=1.8) in your PATH." ) 1>&2 exit 1 fi # The location of the start up JAR FUSEKI_START=${FUSEKI_START:-$FUSEKI_HOME/fuseki-server.jar} # Deal with Cygwin path issues if [ "$cygwin" == "true" ] then FUSEKI_START=`cygpath -w "$FUSEKI_START"` fi # Some JVM settings if [ -z "$JAVA_OPTIONS" ] then JAVA_OPTIONS="-Xmx1200M" fi # Default Fuseki Arguments if [ -z "$FUSEKI_ARGS" ] then if [ -z "$FUSEKI_CONF" ] then FUSEKI_ARGS="" else FUSEKI_ARGS="--config=$FUSEKI_CONF" fi fi # Run command if [ -z "$FUSEKI_CLASSES" ] then RUN_ARGS=(${JAVA_OPTIONS[@]} -jar "$FUSEKI_START" "${FUSEKI_ADDITIONAL_ARGS[@]}" $FUSEKI_ARGS) else RUN_ARGS=(${JAVA_OPTIONS[@]} -cp "$FUSEKI_START:$FUSEKI_CLASSES" org.apache.jena.fuseki.cmd.FusekiCmd "${FUSEKI_ADDITIONAL_ARGS[@]}" $FUSEKI_ARGS) fi RUN_CMD=("$JAVA" "${RUN_ARGS[@]}") # Export the variables to be seen by the java server process. export FUSEKI_HOME export FUSEKI_BASE ##################################################### # Comment these out after you're happy with what # the script is doing. ##################################################### if (( DEBUG )) then log_daemon_msg "FUSEKI_HOME = $FUSEKI_HOME" log_daemon_msg "FUSEKI_BASE = $FUSEKI_BASE" log_daemon_msg "FUSEKI_CONF = $FUSEKI_CONF" log_daemon_msg "FUSEKI_RUN = $FUSEKI_RUN" log_daemon_msg "FUSEKI_PID = $FUSEKI_PID" log_daemon_msg "FUSEKI_ARGS = $FUSEKI_ARGS" log_daemon_msg "FUSEKI_START = $FUSEKI_START" log_daemon_msg "FUSEKI_CLASSES = $FUSEKI_CLASSES" log_daemon_msg "CONFIGS = ${CONFIGS[*]}" log_daemon_msg "JAVA = $JAVA" log_daemon_msg "JAVA_OPTIONS = ${JAVA_OPTIONS[*]}" log_daemon_msg "RUN_ARGS = ${RUN_ARGS[@]}" log_daemon_msg "RUN_CMD = ${RUN_CMD[@]}" log_daemon_msg "Stdout/stderr = $FUSEKI_LOGS_STDERROUT" fi NO_START=${NO_START:-0} # Life cycle functions start() { if (( NO_START )); then log_daemon_msg "Not starting Fuseki - NO_START=1" exit fi # Make sure the data and log directories exist mkdir -p "$FUSEKI_LOGS" if [ ! -z "$FUSEKI_USER" ] then chown "$FUSEKI_USER" "$FUSEKI_LOGS" fi # Make sure the .jar file exists if [ ! -e $FUSEKI_START ]; then log_daemon_msg "Could not see Fuseki .jar file: \$FUSEKI_START has value '$FUSEKI_START'" exit 1 fi log_begin_msg "Starting Fuseki" if type start-stop-daemon > /dev/null 2>&1 then unset CH_USER if [ -n "$FUSEKI_USER" ] then CH_USER="--chuid $FUSEKI_USER" fi if start-stop-daemon --start $CH_USER --chdir "$FUSEKI_HOME" --background --make-pidfile --pidfile "$FUSEKI_PID" --startas /bin/bash -- -c "exec $JAVA ${RUN_ARGS[*]} > $FUSEKI_LOGS_STDERROUT 2>&1" then sleep 2 if running "$FUSEKI_PID" then log_end_msg 0 print_started else log_end_msg 1 fi else log_end_msg 1 log_daemon_msg "** start-stop-daemon failed to run" fi else if running $FUSEKI_PID then log_end_msg 1 log_daemon_msg 'Already Running!' exit 1 else # dead pid file - remove rm -f "$FUSEKI_PID" fi # use subshell to cd to FUSKEI_HOME directory and execute (cd "$FUSEKI_HOME" if [ "$FUSEKI_USER" ] then touch "$FUSEKI_PID" chown "$FUSEKI_USER" "$FUSEKI_PID" ## if [ "$FUSEKI_LOGS_STDERROUT" != "$FUSEKI_LOGS/stderrout.log" ]] ## then ## log_daemon_msg "Redirecting Fuseki stderr/stdout to $FUSEKI_LOGS_STDERROUT" ## fi ## su with login, passing over environment variables. su - "$FUSEKI_USER" -c " export FUSEKI_BASE='${FUSEKI_BASE}' export FUSEKI_HOME='${FUSEKI_HOME}' exec ${RUN_CMD[*]} &> '$FUSEKI_LOGS_STDERROUT' & disown \$! echo \$! > '$FUSEKI_PID'" else exec "${RUN_CMD[@]}" &> "$FUSEKI_LOGS_STDERROUT" & disown $! echo $! > "$FUSEKI_PID" fi ) log_end_msg 0 print_started fi } print_started() { log_daemon_msg "STARTED Fuseki `date`" log_daemon_msg "PID=$(cat "$FUSEKI_PID" 2>/dev/null)" } delete_fuseki_pid_file() { rm -f "$FUSEKI_PID" } stop() { log_begin_msg "Stopping Fuseki: " if ! running "$FUSEKI_PID" then log_end_msg 1 # if a stop rather than a restart, signal failure to stop if [ -z "$1" ] then exit 1 fi fi ############################################################### # !!!! This code needs to be improved, too many repeats !!!! # ############################################################### if type start-stop-daemon > /dev/null 2>&1; then start-stop-daemon --stop --pidfile "$FUSEKI_PID" --chdir "$FUSEKI_HOME" --startas "$JAVA" --signal HUP ## Die after a 30 second timeout TIMEOUT=30 while running "$FUSEKI_PID"; do if (( TIMEOUT-- == 0 )); then start-stop-daemon --stop --pidfile "$FUSEKI_PID" --chdir "$FUSEKI_HOME" --startas "$JAVA" --signal KILL fi sleep 1 done delete_fuseki_pid_file log_end_msg 0 else PID=$(cat "$FUSEKI_PID" 2>/dev/null) kill "$PID" 2>/dev/null TIMEOUT=30 while running $FUSEKI_PID; do if (( TIMEOUT-- == 0 )); then kill -KILL "$PID" 2>/dev/null fi sleep 1 done delete_fuseki_pid_file log_end_msg 0 fi } # Run in the foreground, as the current user run() { # Make sure the .jar file exists if [ ! -e $FUSEKI_START ]; then log_daemon_msg "Could not see Fuseki .jar file: \$FUSEKI_START has value '$FUSEKI_START'" exit 1 fi exec "${RUN_CMD[@]}" } case $CMD in start) start ;; stop) stop ;; restart) stop "restarting" start ;; run) run ;; status) if running $FUSEKI_PID then PID=`cat "$FUSEKI_PID"` log_daemon_msg "Fuseki is running with pid: $PID" else log_daemon_msg "Fuseki is not running" fi ;; *) usage ;; esac exit 0