1544a38ddSChristopher Lenz#! /bin/sh -e
2544a38ddSChristopher Lenz
3544a38ddSChristopher Lenz# Licensed under the Apache License, Version 2.0 (the "License"); you may not
469d1f1d0SNoah Slater# use this file except in compliance with the License. You may obtain a copy of
5544a38ddSChristopher Lenz# the License at
6544a38ddSChristopher Lenz#
7544a38ddSChristopher Lenz#   http://www.apache.org/licenses/LICENSE-2.0
8544a38ddSChristopher Lenz#
9544a38ddSChristopher Lenz# Unless required by applicable law or agreed to in writing, software
10544a38ddSChristopher Lenz# distributed under the License is distributed on an "AS IS" BASIS, WITHOUT
1169d1f1d0SNoah Slater# WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the
12544a38ddSChristopher Lenz# License for the specific language governing permissions and limitations under
13544a38ddSChristopher Lenz# the License.
14544a38ddSChristopher Lenz
1513c7fee8SNoah SlaterBACKGROUND=false
16c6a29006STrond NorbyeDEFAULT_CONFIG_DIR=${CMAKE_INSTALL_PREFIX}/etc/couchdb/default.d
17c6a29006STrond NorbyeDEFAULT_CONFIG_FILE=${CMAKE_INSTALL_PREFIX}/etc/couchdb/default.ini
1830b17649SFilipe David MananaERL_OS_MON_OPTIONS="-os_mon \
1930b17649SFilipe David Manana    start_memsup false \
2030b17649SFilipe David Manana    start_cpu_sup false \
2130b17649SFilipe David Manana    disk_space_check_interval 1 \
2230b17649SFilipe David Manana    disk_almost_full_threshold 1"
2330b17649SFilipe David MananaERL_START_OPTIONS="$ERL_OS_MON_OPTIONS -sasl errlog_type error +K true +A 4"
242bc242fdSNoah SlaterHEART_BEAT_TIMEOUT=11
25c6a29006STrond NorbyeHEART_COMMAND="'${CMAKE_INSTALL_PREFIX}/bin/couchdb' -k"
262bc242fdSNoah SlaterINTERACTIVE=false
2713c7fee8SNoah SlaterKILL=false
28c6a29006STrond NorbyeLOCAL_CONFIG_DIR=${CMAKE_INSTALL_PREFIX}/etc/couchdb/local.d
29c6a29006STrond NorbyeLOCAL_CONFIG_FILE=${CMAKE_INSTALL_PREFIX}/etc/couchdb/local.ini
30c6a29006STrond NorbyePID_FILE=${CMAKE_INSTALL_PREFIX}/var/run/couchdb/couchdb.pid
3113c7fee8SNoah SlaterRECURSED=false
3213c7fee8SNoah SlaterRESET_CONFIG=true
33544a38ddSChristopher LenzRESPAWN_TIMEOUT=0
342bc242fdSNoah SlaterSCRIPT_ERROR=1
352bc242fdSNoah SlaterSCRIPT_OK=0
362bc242fdSNoah SlaterSHUTDOWN=false
37544a38ddSChristopher LenzSTDERR_FILE=couchdb.stderr
382bc242fdSNoah SlaterSTDOUT_FILE=couchdb.stdout
39544a38ddSChristopher Lenz
402bc242fdSNoah Slaterprint_arguments=""
412bc242fdSNoah Slaterstart_arguments=""
422bc242fdSNoah Slaterbackground_start_arguments=""
43544a38ddSChristopher Lenz
44c6a29006STrond Norbyebasename=`basename $0`
45544a38ddSChristopher Lenz
46544a38ddSChristopher Lenzdisplay_version () {
47544a38ddSChristopher Lenz    cat << EOF
48c6a29006STrond Norbye$basename - Apache CouchDB ${COUCHDB_VERSION}
49544a38ddSChristopher Lenz
50544a38ddSChristopher LenzLicensed under the Apache License, Version 2.0 (the "License"); you may not use
51350811a3SNoah Slaterthis file except in compliance with the License. You may obtain a copy of the
52544a38ddSChristopher LenzLicense at
53544a38ddSChristopher Lenz
54544a38ddSChristopher Lenz  http://www.apache.org/licenses/LICENSE-2.0
55544a38ddSChristopher Lenz
56544a38ddSChristopher LenzUnless required by applicable law or agreed to in writing, software distributed
57544a38ddSChristopher Lenzunder the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR
58350811a3SNoah SlaterCONDITIONS OF ANY KIND, either express or implied. See the License for the
59544a38ddSChristopher Lenzspecific language governing permissions and limitations under the License.
60350811a3SNoah Slater
61544a38ddSChristopher LenzEOF
62350811a3SNoah Slater}
63544a38ddSChristopher Lenz
64544a38ddSChristopher Lenzdisplay_help () {
65544a38ddSChristopher Lenz    cat << EOF
66544a38ddSChristopher LenzUsage: $basename [OPTION]
67544a38ddSChristopher Lenz
68c6a29006STrond NorbyeThe $basename command runs the Apache CouchDB server.
69544a38ddSChristopher Lenz
705e803151SNoah SlaterErlang is called with:
715e803151SNoah Slater
72bbd0703fSJan Lehnardt    $ERL_START_OPTIONS
735e803151SNoah Slater
7445aff15bSNoah SlaterErlang inherits the environment of this command.
7545aff15bSNoah Slater
76ceada3e6SNoah SlaterYou can override these options using the environment:
775e803151SNoah Slater
785e803151SNoah Slater    ERL_AFLAGS, ERL_FLAGS, ERL_ZFLAGS
795e803151SNoah Slater
805e803151SNoah SlaterSee erl(1) for more information about the environment variables.
815e803151SNoah Slater
82544a38ddSChristopher LenzThe exit status is 0 for success or 1 for failure.
83544a38ddSChristopher Lenz
84544a38ddSChristopher LenzOptions:
85544a38ddSChristopher Lenz
86544a38ddSChristopher Lenz  -h          display a short help message and exit
87544a38ddSChristopher Lenz  -V          display version information and exit
882bc242fdSNoah Slater  -a FILE     add configuration FILE to chain
895d257408SNoah Slater  -A DIR      add configuration DIR to chain
902bc242fdSNoah Slater  -n          reset configuration file chain (including system default)
912bc242fdSNoah Slater  -c          print configuration file chain and exit
92544a38ddSChristopher Lenz  -i          use the interactive Erlang shell
93544a38ddSChristopher Lenz  -b          spawn as a background process
942bc4be3dSJan Lehnardt  -p FILE     set the background PID FILE (overrides system default)
95544a38ddSChristopher Lenz  -r SECONDS  respawn background process after SECONDS (defaults to no respawn)
96544a38ddSChristopher Lenz  -o FILE     redirect background stdout to FILE (defaults to $STDOUT_FILE)
97544a38ddSChristopher Lenz  -e FILE     redirect background stderr to FILE (defaults to $STDERR_FILE)
98544a38ddSChristopher Lenz  -s          display the status of the background process
99544a38ddSChristopher Lenz  -k          kill the background process, will respawn if needed
100544a38ddSChristopher Lenz  -d          shutdown the background process
101544a38ddSChristopher Lenz
102c6a29006STrond NorbyeReport bugs at <https://www.couchbase.com/issues>.
103544a38ddSChristopher LenzEOF
104544a38ddSChristopher Lenz}
105544a38ddSChristopher Lenz
106544a38ddSChristopher Lenzdisplay_error () {
107544a38ddSChristopher Lenz    if test -n "$1"; then
108544a38ddSChristopher Lenz        echo $1 >&2
109544a38ddSChristopher Lenz    fi
110544a38ddSChristopher Lenz    echo >&2
111544a38ddSChristopher Lenz    echo "Try \`"$basename" -h' for more information." >&2
1122bc242fdSNoah Slater    false
113544a38ddSChristopher Lenz}
114544a38ddSChristopher Lenz
115544a38ddSChristopher Lenz_get_pid () {
116544a38ddSChristopher Lenz    if test -f $PID_FILE; then
1175d6be4a5SNoah Slater        PID=`cat $PID_FILE`
118544a38ddSChristopher Lenz    fi
119544a38ddSChristopher Lenz    echo $PID
120544a38ddSChristopher Lenz}
121544a38ddSChristopher Lenz
1222bc242fdSNoah Slater_add_config_file () {
1232bc242fdSNoah Slater    if test -z "$print_arguments"; then
1242bc242fdSNoah Slater        print_arguments="$1"
1252bc242fdSNoah Slater    else
1262bc242fdSNoah Slater        print_arguments="`cat <<EOF
1272bc242fdSNoah Slater$print_arguments
1282bc242fdSNoah Slater$1
1292bc242fdSNoah SlaterEOF
1302bc242fdSNoah Slater`"
1312bc242fdSNoah Slater    fi
1328449922eSDustin Sallings    start_arguments="$start_arguments '$1'"
1338449922eSDustin Sallings    background_start_arguments="$background_start_arguments -a '$1'"
1342bc242fdSNoah Slater}
1352bc242fdSNoah Slater
1362bc242fdSNoah Slater_add_config_dir () {
1371ea5ee0bSJan Lehnardt    for file in "$1"/*.ini; do
1386a6a8194SJan Lehnardt        if [ -r "$file" ]; then
1396a6a8194SJan Lehnardt          _add_config_file "$file"
1406a6a8194SJan Lehnardt        fi
1412bc242fdSNoah Slater    done
1422bc242fdSNoah Slater}
1432bc242fdSNoah Slater
1442bc242fdSNoah Slater_load_config () {
1452bc242fdSNoah Slater    _add_config_file "$DEFAULT_CONFIG_FILE"
1462bc242fdSNoah Slater    _add_config_dir "$DEFAULT_CONFIG_DIR"
1472bc242fdSNoah Slater    _add_config_file "$LOCAL_CONFIG_FILE"
1482bc242fdSNoah Slater    _add_config_dir "$LOCAL_CONFIG_DIR"
149161181c8SDustin Sallings    if [ "$COUCHDB_ADDITIONAL_CONFIG_FILE" != '' ]
150161181c8SDustin Sallings    then
151161181c8SDustin Sallings        _add_config_file "$COUCHDB_ADDITIONAL_CONFIG_FILE"
152161181c8SDustin Sallings    fi
1532bc242fdSNoah Slater}
1542bc242fdSNoah Slater
1552bc242fdSNoah Slater_reset_config () {
1562bc242fdSNoah Slater    print_arguments=""
1572bc242fdSNoah Slater    start_arguments=""
15885d1cbfcSAdam Kocoloski    background_start_arguments="-n"
1592bc242fdSNoah Slater}
1602bc242fdSNoah Slater
1612bc242fdSNoah Slater_print_config () {
1622bc242fdSNoah Slater    cat <<EOF
1632bc242fdSNoah Slater$print_arguments
1642bc242fdSNoah SlaterEOF
1652bc242fdSNoah Slater}
1662bc242fdSNoah Slater
167544a38ddSChristopher Lenzcheck_status () {
1685d6be4a5SNoah Slater    PID=`_get_pid`
169544a38ddSChristopher Lenz    if test -n "$PID"; then
170544a38ddSChristopher Lenz        if kill -0 $PID 2> /dev/null; then
1712bc4be3dSJan Lehnardt            echo "Apache CouchDB is running as process $PID, time to relax."
172544a38ddSChristopher Lenz            return $SCRIPT_OK
173544a38ddSChristopher Lenz        else
174544a38ddSChristopher Lenz            echo >&2 << EOF
175544a38ddSChristopher LenzApache CouchDB is not running but a stale PID file exists: $PID_FILE"
176544a38ddSChristopher LenzEOF
177544a38ddSChristopher Lenz        fi
178544a38ddSChristopher Lenz    else
179544a38ddSChristopher Lenz        echo "Apache CouchDB is not running." >&2
180544a38ddSChristopher Lenz    fi
181544a38ddSChristopher Lenz    return $SCRIPT_ERROR
182544a38ddSChristopher Lenz}
183544a38ddSChristopher Lenz
184544a38ddSChristopher Lenzcheck_environment () {
18513c7fee8SNoah Slater    if test "$BACKGROUND" != "true"; then
186314a2820SNoah Slater        return
187314a2820SNoah Slater    fi
188314a2820SNoah Slater    touch $PID_FILE 2> /dev/null || true
189314a2820SNoah Slater    touch $STDOUT_FILE 2> /dev/null || true
190314a2820SNoah Slater    touch $STDERR_FILE 2> /dev/null || true
191544a38ddSChristopher Lenz    message_prefix="Apache CouchDB needs write permission on the"
192314a2820SNoah Slater    if test ! -w $PID_FILE; then
193314a2820SNoah Slater        echo "$message_prefix PID file: $PID_FILE" >&2
1942bc242fdSNoah Slater        false
195544a38ddSChristopher Lenz    fi
196314a2820SNoah Slater    if test ! -w $STDOUT_FILE; then
197314a2820SNoah Slater        echo "$message_prefix STDOUT file: $STDOUT_FILE" >&2
1982bc242fdSNoah Slater        false
199544a38ddSChristopher Lenz    fi
200314a2820SNoah Slater    if test ! -w $STDERR_FILE; then
201314a2820SNoah Slater        echo "$message_prefix STDERR file: $STDERR_FILE" >&2
2022bc242fdSNoah Slater        false
203314a2820SNoah Slater    fi
204314a2820SNoah Slater    message_prefix="Apache CouchDB needs a regular"
2052e206a95SNoah Slater    if test `echo 2> /dev/null >> $PID_FILE; echo $?` -gt 0; then
206314a2820SNoah Slater        echo "$message_prefix PID file: $PID_FILE" >&2
2072bc242fdSNoah Slater        false
208314a2820SNoah Slater    fi
2092e206a95SNoah Slater    if test `echo 2> /dev/null >> $STDOUT_FILE; echo $?` -gt 0; then
210314a2820SNoah Slater        echo "$message_prefix STDOUT file: $STDOUT_FILE" >&2
2112bc242fdSNoah Slater        false
212314a2820SNoah Slater    fi
2132e206a95SNoah Slater    if test `echo 2> /dev/null >> $STDERR_FILE; echo $?` -gt 0; then
214314a2820SNoah Slater        echo "$message_prefix STDERR file: $STDERR_FILE" >&2
2152bc242fdSNoah Slater        false
216544a38ddSChristopher Lenz    fi
217544a38ddSChristopher Lenz}
218544a38ddSChristopher Lenz
219544a38ddSChristopher Lenzstart_couchdb () {
22013c7fee8SNoah Slater    if test ! "$RECURSED" = "true"; then
221544a38ddSChristopher Lenz        if check_status 2> /dev/null; then
2222bc242fdSNoah Slater            exit
223544a38ddSChristopher Lenz        fi
224544a38ddSChristopher Lenz        check_environment
225544a38ddSChristopher Lenz    fi
226544a38ddSChristopher Lenz    interactive_option="+Bd -noinput"
22713c7fee8SNoah Slater    if test "$INTERACTIVE" = "true"; then
228544a38ddSChristopher Lenz        interactive_option=""
229544a38ddSChristopher Lenz    fi
23013c7fee8SNoah Slater    if test "$BACKGROUND" = "true"; then
231544a38ddSChristopher Lenz        touch $PID_FILE
232544a38ddSChristopher Lenz        interactive_option="+Bd -noinput"
233544a38ddSChristopher Lenz    fi
234c6a29006STrond Norbye    ERL_LIBS="$ERL_LIBS:'${CMAKE_INSTALL_PREFIX}/lib/couchdb/erlang/lib'"
2358449922eSDustin Sallings
2368449922eSDustin Sallings    # Find plugins and add them to the Erlang path.
237c6a29006STrond Norbye    if test -d "${CMAKE_INSTALL_PREFIX}/lib/couchdb/erlang/lib/../../plugins"; then
238c6a29006STrond Norbye        for plugin in "${CMAKE_INSTALL_PREFIX}/lib/couchdb/erlang/lib/../../plugins"/*; do
2398449922eSDustin Sallings            if echo "$ERL_ZFLAGS" | grep "$plugin/ebin" > /dev/null 2> /dev/null; then
2408449922eSDustin Sallings                : # It's already loaded.
2418449922eSDustin Sallings            else
2428449922eSDustin Sallings                if echo "$COUCH_PLUGIN_BLACKLIST" | grep "$plugin" > /dev/null 2> /dev/null; then
2438449922eSDustin Sallings                    : # Do not use this plugin.
2448449922eSDustin Sallings                else
2458449922eSDustin Sallings                    ERL_ZFLAGS="$ERL_ZFLAGS -pz '$plugin/ebin'"
2467ef409ddSVolker Mische                    if test -d "$plugin/deps"; then
2477ef409ddSVolker Mische                        ERL_LIBS="$ERL_LIBS:'$plugin/deps'"
2487ef409ddSVolker Mische                    fi
2498449922eSDustin Sallings                fi
2508449922eSDustin Sallings            fi
2518449922eSDustin Sallings        done
2528449922eSDustin Sallings        export ERL_ZFLAGS
2538449922eSDustin Sallings    fi
2548449922eSDustin Sallings
255c6a29006STrond Norbye    command="'${ERL_EXECUTABLE}' $interactive_option $ERL_START_OPTIONS \
256c6a29006STrond Norbye        -env ERL_LIBS $ERL_LIBS -couch_ini $start_arguments -s couch"
2577ef409ddSVolker Mische
2582bc242fdSNoah Slater    if test "$BACKGROUND" = "true" -a "$RECURSED" = "false"; then
259b1d05573SJan Lehnardt        $0 $background_start_arguments -b -r $RESPAWN_TIMEOUT -p $PID_FILE \
260544a38ddSChristopher Lenz            -o $STDOUT_FILE -e $STDERR_FILE -R &
2612bc4be3dSJan Lehnardt        echo "Apache CouchDB has started, time to relax."
262544a38ddSChristopher Lenz    else
26313c7fee8SNoah Slater        if test "$RECURSED" = "true"; then
264544a38ddSChristopher Lenz            while true; do
265544a38ddSChristopher Lenz                export HEART_COMMAND
266544a38ddSChristopher Lenz                export HEART_BEAT_TIMEOUT
2675d6be4a5SNoah Slater                `eval $command -pidfile $PID_FILE -heart \
26885323384SNoah Slater                    >> $STDOUT_FILE 2>> $STDERR_FILE` || true
2695d6be4a5SNoah Slater                PID=`_get_pid`
270544a38ddSChristopher Lenz                if test -n "$PID"; then
271544a38ddSChristopher Lenz                    if kill -0 $PID 2> /dev/null; then
272544a38ddSChristopher Lenz                        return $SCRIPT_ERROR
273544a38ddSChristopher Lenz                    fi
274544a38ddSChristopher Lenz                else
275544a38ddSChristopher Lenz                    return $SCRIPT_OK
276544a38ddSChristopher Lenz                fi
277544a38ddSChristopher Lenz                if test "$RESPAWN_TIMEOUT" = "0"; then
278544a38ddSChristopher Lenz                    return $SCRIPT_OK
279544a38ddSChristopher Lenz                fi
280544a38ddSChristopher Lenz                if test "$RESPAWN_TIMEOUT" != "1"; then
281544a38ddSChristopher Lenz                    plural_ending="s"
282544a38ddSChristopher Lenz                fi
283544a38ddSChristopher Lenz                cat << EOF
284544a38ddSChristopher LenzApache CouchDB crashed, restarting in $RESPAWN_TIMEOUT second$plural_ending.
285544a38ddSChristopher LenzEOF
286544a38ddSChristopher Lenz                sleep $RESPAWN_TIMEOUT
287544a38ddSChristopher Lenz            done
288544a38ddSChristopher Lenz        else
2898449922eSDustin Sallings            eval exec "$command"
290544a38ddSChristopher Lenz        fi
291544a38ddSChristopher Lenz    fi
292544a38ddSChristopher Lenz}
293544a38ddSChristopher Lenz
294544a38ddSChristopher Lenzstop_couchdb () {
2955d6be4a5SNoah Slater    PID=`_get_pid`
296544a38ddSChristopher Lenz    if test -n "$PID"; then
297544a38ddSChristopher Lenz        if test "$1" = "false"; then
298544a38ddSChristopher Lenz            echo > $PID_FILE
299544a38ddSChristopher Lenz        fi
300544a38ddSChristopher Lenz        if kill -0 $PID 2> /dev/null; then
301544a38ddSChristopher Lenz            if kill -1 $PID 2> /dev/null; then
302544a38ddSChristopher Lenz                if test "$1" = "false"; then
303544a38ddSChristopher Lenz                    echo "Apache CouchDB has been shutdown."
304544a38ddSChristopher Lenz                else
305544a38ddSChristopher Lenz                    echo "Apache CouchDB has been killed."
306544a38ddSChristopher Lenz                fi
307544a38ddSChristopher Lenz                return $SCRIPT_OK
308544a38ddSChristopher Lenz            else
309544a38ddSChristopher Lenz                echo "Apache CouchDB could not be killed." >&2
310544a38ddSChristopher Lenz                return $SCRIPT_ERROR
311544a38ddSChristopher Lenz            fi
312544a38ddSChristopher Lenz            if test "$1" = "false"; then
313544a38ddSChristopher Lenz                echo "Stale PID file exists but Apache CouchDB is not running."
314544a38ddSChristopher Lenz            else
315544a38ddSChristopher Lenz                echo "Stale PID file existed but Apache CouchDB is not running."
316544a38ddSChristopher Lenz            fi
317544a38ddSChristopher Lenz        fi
318544a38ddSChristopher Lenz    else
319544a38ddSChristopher Lenz        echo "Apache CouchDB is not running."
320544a38ddSChristopher Lenz    fi
321544a38ddSChristopher Lenz}
322544a38ddSChristopher Lenz
323544a38ddSChristopher Lenzparse_script_option_list () {
3242bc242fdSNoah Slater    _load_config
32593bd2f4bSNoah Slater    set +e
3265d257408SNoah Slater    options=`getopt hVa:A:ncibp:r:Ro:e:skd $@`
32793bd2f4bSNoah Slater    if test ! $? -eq 0; then
328544a38ddSChristopher Lenz        display_error
329544a38ddSChristopher Lenz    fi
33093bd2f4bSNoah Slater    set -e
3310e7a43f5SNoah Slater    eval set -- $options
332544a38ddSChristopher Lenz    while [ $# -gt 0 ]; do
333544a38ddSChristopher Lenz        case "$1" in
3342bc242fdSNoah Slater            -h) shift; display_help; exit;;
3352bc242fdSNoah Slater            -V) shift; display_version; exit;;
3362bc242fdSNoah Slater            -a) shift; _add_config_file "$1"; shift;;
3375d257408SNoah Slater            -A) shift; _add_config_dir "$1"; shift;;
3382bc242fdSNoah Slater            -n) shift; _reset_config;;
3392bc242fdSNoah Slater            -c) shift; _print_config; exit;;
34013c7fee8SNoah Slater            -i) shift; INTERACTIVE=true;;
34113c7fee8SNoah Slater            -b) shift; BACKGROUND=true;;
342544a38ddSChristopher Lenz            -r) shift; RESPAWN_TIMEOUT=$1; shift;;
34313c7fee8SNoah Slater            -R) shift; RECURSED=true;;
344544a38ddSChristopher Lenz            -p) shift; PID_FILE=$1; shift;;
345544a38ddSChristopher Lenz            -o) shift; STDOUT_FILE=$1; shift;;
346544a38ddSChristopher Lenz            -e) shift; STDERR_FILE=$1; shift;;
3472bc242fdSNoah Slater            -s) shift; check_status; exit;;
34813c7fee8SNoah Slater            -k) shift; KILL=true;;
34913c7fee8SNoah Slater            -d) shift; SHUTDOWN=true;;
350544a38ddSChristopher Lenz            --) shift; break;;
351544a38ddSChristopher Lenz            *) display_error "Unknown option: $1" >&2;;
352544a38ddSChristopher Lenz        esac
353544a38ddSChristopher Lenz    done
35413c7fee8SNoah Slater    if test "$KILL" = "true" -o "$SHUTDOWN" = "true"; then
35513c7fee8SNoah Slater        stop_couchdb $KILL
356544a38ddSChristopher Lenz    else
357544a38ddSChristopher Lenz        start_couchdb
358544a38ddSChristopher Lenz    fi
359544a38ddSChristopher Lenz}
360544a38ddSChristopher Lenz
361544a38ddSChristopher Lenzparse_script_option_list $@