#!/bin/bash
### BEGIN REDHAT INFO
# chkconfig: 2345 99 20
# description: The Neo4J graph database server. See http://neo4j.org
### END REDHAT INFO
### BEGIN INIT INFO
# Provides: neo4j-service
# Required-Start:
# Required-Stop:
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
### END INIT INFO
# Copyright (c) 2002-2013 "Neo Technology,"
# Network Engine for Objects in Lund AB [http://neotechnology.com]
#
# This file is part of Neo4j.
#
# Neo4j is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# This program is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program. If not, see .
FRIENDLY_NAME="Neo4j Server"
LAUNCHD_NAME="org.neo4j.server"
function findBaseDirAndCdThere {
# This seems to not be safe to run at any time. If that
# is the case, it should be fixed to be so, if possible.
SCRIPT=$0
cd "`dirname "$SCRIPT"`"
SCRIPT=`basename "$SCRIPT"`
while [ -L "$SCRIPT" ]
do
SCRIPT=$( readlink "$SCRIPT" )
cd "$(dirname "$SCRIPT")"
SCRIPT=`basename "$SCRIPT"`
done
NEO4J_HOME=`cd $( dirname "$SCRIPT" )/.. && dirs -l +0`
NEO4J_INSTANCE=$NEO4J_HOME
NEO4J_CONFIG=$NEO4J_INSTANCE/conf
NEO4J_LOG=$NEO4J_INSTANCE/data/log
cd "$NEO4J_HOME"
}
function parseConfig {
if [ ${BASH_VERSINFO[0]} -eq 3 ] ; then
if [ ${BASH_VERSINFO[1]} -lt 2 ] ; then
getconfigquoted "${NEO4J_CONFIG}/neo4j-wrapper.conf"
getconfigquoted "${NEO4J_CONFIG}/neo4j-server.properties"
return
fi
fi
getconfig "${NEO4J_CONFIG}/neo4j-wrapper.conf"
getconfig "${NEO4J_CONFIG}/neo4j-server.properties"
}
findBaseDirAndCdThere
source bin/utils
parseConfig
JAVA_OPTS="-server -XX:+DisableExplicitGC ${wrapper_java_additional}"
[ -z "${wrapper_java_initmemory}" ] || JAVA_OPTS="$JAVA_OPTS -Xms${wrapper_java_initmemory}m"
[ -z "${wrapper_java_maxmemory}" ] || JAVA_OPTS="$JAVA_OPTS -Xmx${wrapper_java_maxmemory}m"
#NEO4J_SERVER_PORT=`( egrep "^org.neo4j.server.webserver.port" $NEO4J_INSTANCE/conf/neo4j-server.properties || echo 7474 ) | sed -e 's/.*=//'`
NEO4J_SERVER_PORT=${org_neo4j_server_webserver_port:=7474}
LAUNCHD_NAME="${LAUNCHD_NAME}.${NEO4J_SERVER_PORT}"
HEADLESS=false
if [ -z "${wrapper_user}" ]; then
NEO4J_USER=`id -un`
else
NEO4J_USER=${wrapper_user}
fi
# Username to propose for neo4j user, can be overridden by -u USERNAME option
DEFAULT_USER='neo4j'
SCRIPT_NAME="${NEO4J_HOME}/bin/neo4j"
SERVICE_NAME=${wrapper_ntservice_name:=neo4j-service}
LAUNCHD_DIR=~/Library/LaunchAgents/
TIMEOUT=120
PID_FILE=${NEO4J_INSTANCE}/data/neo4j-service.pid
buildclasspath() {
# confirm library jars
LIBDIR="$NEO4J_HOME"/lib
if [ ! -e "$LIBDIR" ] ; then
echo "Error: missing Neo4j Library, expected at $LIBDIR"
exit 1
fi
# confirm system jars
SYSLIBDIR="$NEO4J_HOME"/system/lib
if [ ! -e "$SYSLIBDIR" ] ; then
echo "Error: missing Neo4j System Library, expected at $SYSLIBDIR"
exit 1
fi
ALL_JARS=""
for jar in "$LIBDIR"/*.jar "$SYSLIBDIR"/*.jar ; do
[ -z "$ALL_JARS" ] && ALL_JARS="$jar" || ALL_JARS="$ALL_JARS":"$jar"
done
# add any plugin jars
for jar in "$NEO4J_HOME"/plugins/*.jar ; do
if [ -e "$jar" ] ; then
ALL_JARS="$ALL_JARS":"$jar"
fi
done
# add any plugin jars in nested folders
for jar in "$NEO4J_HOME"/plugins/**/*.jar ; do
if [ -e "$jar" ] ; then
ALL_JARS="$ALL_JARS":"$jar"
fi
done
CLASSPATH=${ALL_JARS}
# add useful conf stuff to classpath - always a good idea
CLASSPATH="$CLASSPATH":"$NEO4J_HOME"/conf/
}
detectrunning() {
if [ $DIST_OS = "solaris" ] ; then
## SmartOS has a different lsof command line arguments
newpid=$(lsof -o $NEO4J_SERVER_PORT | grep '::' | head -n1 | cut -d ' ' -f 1)
else
## This could be achieved with filtering using -sTCP:LISTEN but this option is not available
## on lsof v4.78 which is the one bundled with some distros. So we have to do this grep below
newpid=$(lsof -i :$NEO4J_SERVER_PORT -F T -Ts | grep -i "TST=LISTEN" -B1 | head -n1)
newpid=${newpid:1}
fi
}
startit() {
detectos
exitonnojava
checkstatus
checklimits
checkjvmcompatibility
detectrunning
if [ $newpid ] ; then
echo "Another server-process is running with [$newpid], cannot start a new one. Exiting."
exit 2;
fi
echo "Using additional JVM arguments: " $JAVA_OPTS
if [ $DIST_OS = "macosx" ] ; then
getlaunchdpid
if [ $LAUNCHDPID -eq 0 ] ; then
echo "Detected installation in launchd, starting it..."
launchctl start $LAUNCHD_NAME
exit 0
elif [ $LAUNCHDPID -gt 0 ] ; then
echo "Instance already running via launchd with PID $LAUNCHDPID"
exit 1
fi
# We fall through here since if there is no launchd install we start manually
fi
if [ -z $NEO4J_PID ] ; then
printf "Starting $FRIENDLY_NAME..."
buildclasspath
checkclasspath
checkandrepairenv
CONSOLE_LOG="$NEO4J_LOG/console.log"
if [ $UID == 0 ] ; then
su $NEO4J_USER -c "\"$JAVACMD\" -cp '$CLASSPATH' $JAVA_OPTS \
-Dneo4j.home=\"${NEO4J_HOME}\" -Dneo4j.instance=\"${NEO4J_INSTANCE}\" \
-Dfile.encoding=UTF-8 \
org.neo4j.server.Bootstrapper >> \"${CONSOLE_LOG}\" 2>&1 & echo \$! > \"$PID_FILE\" "
else
checkwriteaccess
echo "WARNING: not changing user"
"$JAVACMD" -cp "${CLASSPATH}" $JAVA_OPTS \
-Dneo4j.home="${NEO4J_HOME}" -Dneo4j.instance="${NEO4J_INSTANCE}" \
-Dfile.encoding=UTF-8 \
org.neo4j.server.Bootstrapper >> "${CONSOLE_LOG}" 2>&1 & echo $! > "${PID_FILE}"
fi
STARTED_PID=$( cat "$PID_FILE" )
if [ "$org_neo4j_server_database_mode" = "HA" ] ; then
if kill -0 $STARTED_PID 2>/dev/null ; then
echo "HA instance started in process [$STARTED_PID]. Will be operational once connected to peers. See ${CONSOLE_LOG} for current status."
exit 0
else
echo "HA instance was unable to start. See ${CONSOLE_LOG}."
rm "$PID_FILE"
exit 1
fi
fi
echo -n "process [$STARTED_PID]"
if [ $WAIT = "true" ] ; then
echo -n "... waiting for server to be ready."
while kill -0 $STARTED_PID 2> /dev/null ; do
## wait for start, pick up the server listening on the port
detectrunning
if [ $newpid ] ; then
break
fi
printf "."
sleep 1
done
if kill -0 $STARTED_PID 2>/dev/null ; then
if [ "$newpid" != "$STARTED_PID" ] ; then
rm "$PID_FILE"
kill -9 $STARTED_PID
echo " Failed to start within $TIMEOUT seconds."
echo "$FRIENDLY_NAME failed to start, please check the logs for details."
echo "If startup is blocked on a long recovery, use '$0 start-no-wait' to give the startup more time."
exit 2
fi
echo " OK."
echo "http://localhost:$NEO4J_SERVER_PORT/ is ready."
exit 0
fi
echo " Failed to start within $TIMEOUT seconds."
echo "$FRIENDLY_NAME may have failed to start, please check the logs."
rm "$PID_FILE"
exit 1
else
echo "...Started the server in the background, returning..."
fi
else
echo "$FRIENDLY_NAME already running with pid $NEO4J_PID"
exit 0
fi
}
console() {
checkstatus
checklimits
if [ -z $NEO4J_PID ] ; then
echo "Starting $FRIENDLY_NAME console-mode..."
exitonnojava
buildclasspath
checkwriteaccess
checkandrepairenv
echo "Using additional JVM arguments: " $JAVA_OPTS
"$JAVACMD" -cp "${CLASSPATH}" $JAVA_OPTS \
-Dneo4j.home="${NEO4J_HOME}" -Dneo4j.instance="${NEO4J_INSTANCE}" \
-Dfile.encoding=UTF-8 \
org.neo4j.server.Bootstrapper
else
echo "$FRIENDLY_NAME already running with pid $NEO4J_PID"
exit 1
fi
}
# Modifies neo4j config to set the effective user when running as a service
# usage: modify_user_config [true|false]
# pass in "true" for created to mark that the user was created (instead than pre-existing)
modify_user_config() {
created=${2:-"false"}
if `grep -q "wrapper\.user=" "$NEO4J_INSTANCE/conf/neo4j-wrapper.conf"` ; then
sed -i -e "s/^.*wrapper\.user=.*$/wrapper\.user=$1/" "$NEO4J_INSTANCE/conf/neo4j-wrapper.conf"
else
echo "wrapper.user=$1" >> "$NEO4J_INSTANCE/conf/neo4j-wrapper.conf"
fi
if `grep -q "wrapper\.user\.created=" "$NEO4J_INSTANCE/conf/neo4j-wrapper.conf"` ; then
sed -i -e "s/^.*wrapper\.user\.created=.*$/wrapper\.user\.created=${created}/" "$NEO4J_INSTANCE/conf/neo4j-wrapper.conf"
else
echo "wrapper.user.created=${created}" >> "$NEO4J_INSTANCE/conf/neo4j-wrapper.conf"
fi
}
installservice() {
detectos
findjava
selectinittool
if [ ! -x "$JAVACMD" ] ; then
if [[ $HEADLESS == false ]]; then
read -p "It was not possible to determine JAVA_HOME. Do you want to continue with the installation? [yN]" yn
else
yn='y'
fi
case $yn in
[yY]* ) echo "WARNING: Alright, but $FRIENDLY_NAME will fail to launch until Java has been properly installed and configured."
;;
* ) echo "Aborting installation."
exit 1
;;
esac
fi
if [[ -d "/etc/init.d" ]]; then
if [[ -e "/etc/init.d/${SERVICE_NAME}" ]]; then
echo "${SERVICE_NAME} already installed."
else
if [ $UID != 0 ] ; then
eval echo 'Must be root to perform this action.'
exit 1
else
checkstatus
if [ ! -z $NEO4J_PID ] ; then
stopit
fi
if [[ $NEO4J_USER == $wrapper_user ]]; then
default_user=$wrapper_user
else
default_user=$DEFAULT_USER
fi
if [[ $HEADLESS == false ]]; then
read -p "Graph-like power should be handled carefully. What user should run Neo4j? [$default_user] " proposed_user
fi
proposed_user=${proposed_user:-$default_user}
if ! `id $proposed_user &> /dev/null` ; then
if [[ $HEADLESS == false ]]; then
read -p "User \"$proposed_user\" does not yet exist. Shall I create the account for you? [Yn]" yn
else
yn="y"
fi
case $yn in
[Nn]* ) echo "WARNING: Alright, but Neo4j will fail to launch until that user has been created."
set_user $proposed_user
;;
* ) create_user $proposed_user
;;
esac
else
modify_user_config $proposed_user
fi
ln -s "${SCRIPT_NAME}" "/etc/init.d/${SERVICE_NAME}"
if [ $INIT_TOOL == 'chkconfig' ]; then
chkconfig --add ${SERVICE_NAME}
else
update-rc.d ${SERVICE_NAME} defaults
fi
chown -R $proposed_user: "$NEO4J_HOME/data" "$NEO4J_HOME/conf"
fi
fi
elif [[ $DIST_OS -eq "macosx" ]] ; then
sed -e "s^NEO4J_INSTANCE^${NEO4J_INSTANCE}^" -e "s^LAUNCHD_NAME^${LAUNCHD_NAME}^" <"${NEO4J_INSTANCE}/bin/org.neo4j.server.plist" >"${LAUNCHD_DIR}/${LAUNCHD_NAME}.plist"
launchctl load -w ${LAUNCHD_DIR}/${LAUNCHD_NAME}.plist
launchctl start ${LAUNCHD_NAME}
else
echo "Sorry, don't know how to install on ${DIST_OS}."
fi
if [ -x "$JAVACMD" ] ; then
if [[ $DIST_OS -ne "macosx" ]] ; then
startit
fi
fi
}
showinfo() {
reportstatus
exitonnojava
buildclasspath
echo "NEO4J_HOME: $NEO4J_HOME"
echo "NEO4J_SERVER_PORT: $NEO4J_SERVER_PORT"
echo "NEO4J_INSTANCE: $NEO4J_INSTANCE"
echo "JAVA_HOME: $JAVA_HOME"
echo "JAVA_OPTS: $JAVA_OPTS"
echo "CLASSPATH: $CLASSPATH"
}
# END FUNCTIONS
# BEGIN MAIN
# Parse option flags
while getopts "u:h" opt; do
case $opt in
h)
echo "Running in headless (-h) mode" >&2
HEADLESS=true
;;
u)
echo "Installing with user $OPTARG"
DEFAULT_USER=$OPTARG
;;
\?)
echo "Invalid option: -$OPTARG" >&2
exit 1
;;
:)
echo "Option -$OPTARG requires an argument." >&2
exit 1
;;
esac
done
case "${!OPTIND}" in
console)
console
exit 0
;;
start)
WAIT=true
startit
;;
start-no-wait)
WAIT=false
startit
exit 0
;;
stop)
stopit
exit 0
;;
restart)
WAIT=true
stopit
startit
exit 0
;;
status)
reportstatus
exit 0
;;
info)
showinfo
exit 0
;;
install)
WAIT=true
installservice
exit 0
;;
remove)
removeservice
exit 0
;;
*)
echo "Usage: neo4j { console | start | start-no-wait | stop | restart | status | info | install | remove }"
exit 0;;
esac
exit $?