#!/bin/sh
#
# Portable SysV init script for the Zabbix agent/server.
#

# Do NOT "set -e".

# These values must match your Zabbix installation.
DAEMON_USER="zabbix"
DAEMON_NAME="zabbix_agentd"
DAEMON_BIN="/opt/zabbix-agent/sbin/$DAEMON_NAME"
DAEMON_CONF="/opt/zabbix-agent/conf/$DAEMON_NAME.conf"
DAEMON_ARGS="-c $DAEMON_CONF"

# These values must match the configuration from the above daemon conf file.
LOG_DIR="/var/log/zabbix"
PID_DIR="/var/run/zabbix"
PID_FILE="$PID_DIR"/$DAEMON_NAME.pid

# Things to customize for your needs.
SERVICE_NAME="Zabbix agent"
# Seconds to wait for a successful status when starting/stopping the daemon.
TIMEOUT_SECONDS=10

#
# Needed directories are created when starting this init script.
#
create_dir_as_needed() {
    if [ ! -d "$1" ]; then
        mkdir "$1" && chown $DAEMON_USER "$1"
    fi
}

#
# Starts the service if properly stopped and waits for it to launch
# successfully for a predefined number of seconds.
#
start_service() {
    status_service 2>/dev/null
    case $? in
        0)
            printf "$SERVICE_NAME is already running, nothing to do.\n"
            exit 0
            ;;
        1|4)
            printf "$SERVICE_NAME was not properly stopped, not starting!\n"
            exit 1
            ;;
    esac
    if [ ! -x "$DAEMON_BIN" ]; then
        printf "$DAEMON_BIN executable not present!\n" >&2
        exit 5
    fi
    create_dir_as_needed "$PID_DIR"
    create_dir_as_needed "$LOG_DIR"
    printf "Starting $SERVICE_NAME: "
    "$DAEMON_BIN" $DAEMON_ARGS
    i=0; while [ $i -lt $TIMEOUT_SECONDS ]; do
        if status_service 2>/dev/null; then
            printf " Done.\n"
            exit 0
        fi
        sleep 1
        printf "."
        i=`expr $i + 1`
    done
    printf "\nCould not properly start $SERVICE_NAME!\n" >&2
    exit 1
}

#
# Stops the service if properly running and waits for it to stop
# successfully for a predefined number of seconds.
#
stop_service() {
    status_service
    case $? in
        3)
            printf "$SERVICE_NAME is not running, nothing to do.\n"
            exit 0
            ;;
        1|4)
            printf "$SERVICE_NAME is not properly running, not stopping!\n"
            exit 1
            ;;
    esac
    printf "Stopping $SERVICE_NAME: "
    i=0; while [ $i -lt $TIMEOUT_SECONDS ]; do
        if status_service 2>/dev/null; then
            kill $SAVED_PID
         else
            printf " Done.\n"
            exit 0
        fi
        sleep 1
        printf "."
        i=`expr $i + 1`
    done
    printf "\nCould not properly stop $SERVICE_NAME!\n" >&2
    exit 1
}

#
# This implements a crude but portable status action for the init script
# without using LSB functions, although respecting the LSB 4.1 error codes.
#
status_service() {
    # A portable ps invocation to get the pids and commands for all processes
    # running as relevant user (without the usual ps headers).
    mem_pids_comms=`ps -u $DAEMON_USER -o pid= -o comm= | grep "$DAEMON_NAME"`
    # Check for processes running under the relevant name.
    if [ -z "$mem_pids_comms" ] ; then
        printf "No $DAEMON_NAME process is running as user $DAEMON_USER.\n" >&2
        return 3
    fi
    # Check for problems related to the PID read from $PID_FILE.
    if [ ! -s "$PID_FILE" ]; then
        printf "Problems reading PID from file $PID_FILE.\n" >&2
        return 4
    fi
    SAVED_PID=`cat "$PID_FILE"`
    matched_pid=`printf "$mem_pids_comms" | awk '{print $1}' | grep "$SAVED_PID"`
    if [ ! "$matched_pid" = "$SAVED_PID" ]; then
        printf "PID from $PID_FILE doesn't match running processes.\n" >&2
        return 4
    fi
    # Check that the corresponding process is responding.
    if ! `kill -0 "$SAVED_PID"`; then
        printf "$SERVICE_NAME is not responding or wrong PID: $SAVED_PID.\n" >&2
        return 1
    fi
}



#
# main
#

# A crude check for a sane installation and configuration.
if [ ! -r "$DAEMON_CONF" ]; then
   printf "Configuration file $DAEMON_CONF not present!\n" >&2
   exit 6
fi

# Check for the user's existence.
if ! id $DAEMON_USER >/dev/null 2>/dev/null; then
    printf "$DAEMON_USER user not present!\n" >&2
    exit 6
fi

# Do not use stop_service() and start_service() for restart/force-reload.
case "$@" in
    start)
        start_service
        ;;
    stop)
        stop_service
        ;;
    restart|force-reload)
        $0 stop
        $0 start
        ;;
    status)
        status_service
        ret_val=$?
        case $ret_val in
            0)
                printf "$SERVICE_NAME is running.\n"
                ;;
            3)
                printf "$SERVICE_NAME is not running!\n"
                ;;
            *)
                printf "$SERVICE_NAME is not properly running!\n"
                ;;
        esac
        exit $ret_val
        ;;
    *)
        printf "Usage: $0 {start|stop|restart|force-reload|status}\n" >&2
        exit 2
        ;;
esac
