1#!/bin/sh
2
3# Copyright 2011 Dvir Volk <dvirsk at gmail dot com>. All rights reserved.
4#
5# Redistribution and use in source and binary forms, with or without
6# modification, are permitted provided that the following conditions are met:
7#
8#   1. Redistributions of source code must retain the above copyright notice,
9#   this list of conditions and the following disclaimer.
10#
11#   2. Redistributions in binary form must reproduce the above copyright
12#   notice, this list of conditions and the following disclaimer in the
13#   documentation and/or other materials provided with the distribution.
14#
15# THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED
16# WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF
17# MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO
18# EVENT SHALL Dvir Volk OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
19# INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
20# LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA,
21# OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF
22# LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING
23# NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE,
24# EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
25#
26################################################################################
27#
28# Service installer for redis server, runs interactively by default.
29#
30# To run this script non-interactively (for automation/provisioning purposes),
31# feed the variables into the script. Any missing variables will be prompted!
32# Tip: Environment variables also support command substitution (see REDIS_EXECUTABLE)
33#
34# Example:
35#
36# sudo REDIS_PORT=1234 \
37# 		 REDIS_CONFIG_FILE=/etc/redis/1234.conf \
38# 		 REDIS_LOG_FILE=/var/log/redis_1234.log \
39# 		 REDIS_DATA_DIR=/var/lib/redis/1234 \
40# 		 REDIS_EXECUTABLE=`command -v redis-server` ./utils/install_server.sh
41#
42# This generates a redis config file and an /etc/init.d script, and installs them.
43#
44# /!\ This script should be run as root
45#
46################################################################################
47
48die () {
49	echo "ERROR: $1. Aborting!"
50	exit 1
51}
52
53
54#Absolute path to this script
55SCRIPT=$(readlink -f $0)
56#Absolute path this script is in
57SCRIPTPATH=$(dirname $SCRIPT)
58
59#Initial defaults
60_REDIS_PORT=6379
61_MANUAL_EXECUTION=false
62
63echo "Welcome to the redis service installer"
64echo "This script will help you easily set up a running redis server"
65echo
66
67#check for root user
68if [ "$(id -u)" -ne 0 ] ; then
69	echo "You must run this script as root. Sorry!"
70	exit 1
71fi
72
73if ! echo $REDIS_PORT | egrep -q '^[0-9]+$' ; then
74	_MANUAL_EXECUTION=true
75	#Read the redis port
76	read  -p "Please select the redis port for this instance: [$_REDIS_PORT] " REDIS_PORT
77	if ! echo $REDIS_PORT | egrep -q '^[0-9]+$' ; then
78		echo "Selecting default: $_REDIS_PORT"
79		REDIS_PORT=$_REDIS_PORT
80	fi
81fi
82
83if [ -z "$REDIS_CONFIG_FILE" ] ; then
84	_MANUAL_EXECUTION=true
85	#read the redis config file
86	_REDIS_CONFIG_FILE="/etc/redis/$REDIS_PORT.conf"
87	read -p "Please select the redis config file name [$_REDIS_CONFIG_FILE] " REDIS_CONFIG_FILE
88	if [ -z "$REDIS_CONFIG_FILE" ] ; then
89		REDIS_CONFIG_FILE=$_REDIS_CONFIG_FILE
90		echo "Selected default - $REDIS_CONFIG_FILE"
91	fi
92fi
93
94if [ -z "$REDIS_LOG_FILE" ] ; then
95	_MANUAL_EXECUTION=true
96	#read the redis log file path
97	_REDIS_LOG_FILE="/var/log/redis_$REDIS_PORT.log"
98	read -p "Please select the redis log file name [$_REDIS_LOG_FILE] " REDIS_LOG_FILE
99	if [ -z "$REDIS_LOG_FILE" ] ; then
100		REDIS_LOG_FILE=$_REDIS_LOG_FILE
101		echo "Selected default - $REDIS_LOG_FILE"
102	fi
103fi
104
105if [ -z "$REDIS_DATA_DIR" ] ; then
106	_MANUAL_EXECUTION=true
107	#get the redis data directory
108	_REDIS_DATA_DIR="/var/lib/redis/$REDIS_PORT"
109	read -p "Please select the data directory for this instance [$_REDIS_DATA_DIR] " REDIS_DATA_DIR
110	if [ -z "$REDIS_DATA_DIR" ] ; then
111		REDIS_DATA_DIR=$_REDIS_DATA_DIR
112		echo "Selected default - $REDIS_DATA_DIR"
113	fi
114fi
115
116if [ ! -x "$REDIS_EXECUTABLE" ] ; then
117	_MANUAL_EXECUTION=true
118	#get the redis executable path
119	_REDIS_EXECUTABLE=`command -v redis-server`
120	read -p "Please select the redis executable path [$_REDIS_EXECUTABLE] " REDIS_EXECUTABLE
121	if [ ! -x "$REDIS_EXECUTABLE" ] ; then
122		REDIS_EXECUTABLE=$_REDIS_EXECUTABLE
123
124		if [ ! -x "$REDIS_EXECUTABLE" ] ; then
125			echo "Mmmmm...  it seems like you don't have a redis executable. Did you run make install yet?"
126			exit 1
127		fi
128	fi
129fi
130
131#check the default for redis cli
132CLI_EXEC=`command -v redis-cli`
133if [ -z "$CLI_EXEC" ] ; then
134	CLI_EXEC=`dirname $REDIS_EXECUTABLE`"/redis-cli"
135fi
136
137echo "Selected config:"
138
139echo "Port           : $REDIS_PORT"
140echo "Config file    : $REDIS_CONFIG_FILE"
141echo "Log file       : $REDIS_LOG_FILE"
142echo "Data dir       : $REDIS_DATA_DIR"
143echo "Executable     : $REDIS_EXECUTABLE"
144echo "Cli Executable : $CLI_EXEC"
145
146if $_MANUAL_EXECUTION == true ; then
147	read -p "Is this ok? Then press ENTER to go on or Ctrl-C to abort." _UNUSED_
148fi
149
150mkdir -p `dirname "$REDIS_CONFIG_FILE"` || die "Could not create redis config directory"
151mkdir -p `dirname "$REDIS_LOG_FILE"` || die "Could not create redis log dir"
152mkdir -p "$REDIS_DATA_DIR" || die "Could not create redis data directory"
153
154#render the templates
155TMP_FILE="/tmp/${REDIS_PORT}.conf"
156DEFAULT_CONFIG="${SCRIPTPATH}/../redis.conf"
157INIT_TPL_FILE="${SCRIPTPATH}/redis_init_script.tpl"
158INIT_SCRIPT_DEST="/etc/init.d/redis_${REDIS_PORT}"
159PIDFILE="/var/run/redis_${REDIS_PORT}.pid"
160
161if [ ! -f "$DEFAULT_CONFIG" ]; then
162	echo "Mmmmm... the default config is missing. Did you switch to the utils directory?"
163	exit 1
164fi
165
166#Generate config file from the default config file as template
167#changing only the stuff we're controlling from this script
168echo "## Generated by install_server.sh ##" > $TMP_FILE
169
170read -r SED_EXPR <<-EOF
171s#^port .\+#port ${REDIS_PORT}#; \
172s#^logfile .\+#logfile ${REDIS_LOG_FILE}#; \
173s#^dir .\+#dir ${REDIS_DATA_DIR}#; \
174s#^pidfile .\+#pidfile ${PIDFILE}#; \
175s#^daemonize no#daemonize yes#;
176EOF
177sed "$SED_EXPR" $DEFAULT_CONFIG >> $TMP_FILE
178
179#cat $TPL_FILE | while read line; do eval "echo \"$line\"" >> $TMP_FILE; done
180cp $TMP_FILE $REDIS_CONFIG_FILE || die "Could not write redis config file $REDIS_CONFIG_FILE"
181
182#Generate sample script from template file
183rm -f $TMP_FILE
184
185#we hard code the configs here to avoid issues with templates containing env vars
186#kinda lame but works!
187REDIS_INIT_HEADER=\
188"#!/bin/sh\n
189#Configurations injected by install_server below....\n\n
190EXEC=$REDIS_EXECUTABLE\n
191CLIEXEC=$CLI_EXEC\n
192PIDFILE=\"$PIDFILE\"\n
193CONF=\"$REDIS_CONFIG_FILE\"\n\n
194REDISPORT=\"$REDIS_PORT\"\n\n
195###############\n\n"
196
197REDIS_CHKCONFIG_INFO=\
198"# REDHAT chkconfig header\n\n
199# chkconfig: - 58 74\n
200# description: redis_${REDIS_PORT} is the redis daemon.\n
201### BEGIN INIT INFO\n
202# Provides: redis_6379\n
203# Required-Start: \$network \$local_fs \$remote_fs\n
204# Required-Stop: \$network \$local_fs \$remote_fs\n
205# Default-Start: 2 3 4 5\n
206# Default-Stop: 0 1 6\n
207# Should-Start: \$syslog \$named\n
208# Should-Stop: \$syslog \$named\n
209# Short-Description: start and stop redis_${REDIS_PORT}\n
210# Description: Redis daemon\n
211### END INIT INFO\n\n"
212
213if command -v chkconfig >/dev/null; then
214	#if we're a box with chkconfig on it we want to include info for chkconfig
215	echo "$REDIS_INIT_HEADER" "$REDIS_CHKCONFIG_INFO" > $TMP_FILE && cat $INIT_TPL_FILE >> $TMP_FILE || die "Could not write init script to $TMP_FILE"
216else
217	#combine the header and the template (which is actually a static footer)
218	echo "$REDIS_INIT_HEADER" > $TMP_FILE && cat $INIT_TPL_FILE >> $TMP_FILE || die "Could not write init script to $TMP_FILE"
219fi
220
221###
222# Generate sample script from template file
223# - No need to check which system we are on. The init info are comments and
224#   do not interfere with update_rc.d systems. Additionally:
225#     Ubuntu/debian by default does not come with chkconfig, but does issue a
226#     warning if init info is not available.
227
228cat > ${TMP_FILE} <<EOT
229#!/bin/sh
230#Configurations injected by install_server below....
231
232EXEC=$REDIS_EXECUTABLE
233CLIEXEC=$CLI_EXEC
234PIDFILE=$PIDFILE
235CONF="$REDIS_CONFIG_FILE"
236REDISPORT="$REDIS_PORT"
237###############
238# SysV Init Information
239# chkconfig: - 58 74
240# description: redis_${REDIS_PORT} is the redis daemon.
241### BEGIN INIT INFO
242# Provides: redis_${REDIS_PORT}
243# Required-Start: \$network \$local_fs \$remote_fs
244# Required-Stop: \$network \$local_fs \$remote_fs
245# Default-Start: 2 3 4 5
246# Default-Stop: 0 1 6
247# Should-Start: \$syslog \$named
248# Should-Stop: \$syslog \$named
249# Short-Description: start and stop redis_${REDIS_PORT}
250# Description: Redis daemon
251### END INIT INFO
252
253EOT
254cat ${INIT_TPL_FILE} >> ${TMP_FILE}
255
256#copy to /etc/init.d
257cp $TMP_FILE $INIT_SCRIPT_DEST && \
258	chmod +x $INIT_SCRIPT_DEST || die "Could not copy redis init script to  $INIT_SCRIPT_DEST"
259echo "Copied $TMP_FILE => $INIT_SCRIPT_DEST"
260
261#Install the service
262echo "Installing service..."
263if command -v chkconfig >/dev/null 2>&1; then
264	# we're chkconfig, so lets add to chkconfig and put in runlevel 345
265	chkconfig --add redis_${REDIS_PORT} && echo "Successfully added to chkconfig!"
266	chkconfig --level 345 redis_${REDIS_PORT} on && echo "Successfully added to runlevels 345!"
267elif command -v update-rc.d >/dev/null 2>&1; then
268	#if we're not a chkconfig box assume we're able to use update-rc.d
269	update-rc.d redis_${REDIS_PORT} defaults && echo "Success!"
270else
271	echo "No supported init tool found."
272fi
273
274/etc/init.d/redis_$REDIS_PORT start || die "Failed starting service..."
275
276#tada
277echo "Installation successful!"
278exit 0
279