random-commands/initscript-samba-ad-dc

222 lines
7.1 KiB
Bash
Executable file

#!/bin/bash
# Version: 0.5.0.
# Variant: service.
# Copyright (c) 2005-2023:
# Darren 'Tadgy' Austin <darren (at) afterdark.org.uk>
# Licensed under the terms of the GNU General Public License version 3.
SERVICE_EXEC="/usr/sbin/samba"
SERVICE_ARGS=()
SERVICE_ENV=()
SERVICE_PIDFILE="/run/samba.pid"
# Allow configuration in /etc/default to override.
# Additional available variables:
# SERVICE_EXTRA_ARGS=() # Extra arguments passed to $SERVICE_EXEC. Must be an array.
# SERVICE_EXTRA_ENV=() # Extra environment passed to $SERVICE_EXEC. Must be an array.
# SLAY_DELAY="" # Delay between the SIGTERM and SIGKILL on a 'stop'. Default: 2s.
# RESTART_DELAY="" # Delay between stopping and starting on a 'restart'. Default: 2s.
[[ -e "/etc/default/${0##*rc.}" ]] && {
# shellcheck disable=SC1090
source "/etc/default/${0##*rc.}" 2>/dev/null || {
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "failed sourcing '/etc/default/${0##*rc.}'" >&2
exit 2
}
}
# Now all possible variable changes are complete, expand out the embedded variables, if any.
eval "$(declare -p SERVICE_EXEC SERVICE_ARGS SERVICE_ENV SERVICE_PIDFILE SERVICE_EXTRA_ARGS SERVICE_EXTRA_ENV \
SLAY_DELAY RESTART_DELAY 2>/dev/null | sed -re 's/\\\$/$/g')" || {
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "failed expanding embedded variables" >&2
exit 2
}
# This function can be used to perform any pre-start tests; hopfully to insure the daemon can start
# correctly, before actually trying to start it.
checkconfigured() {
# Returns:
# 0 - The pre-start tests passed and the service should be started.
# >0 - Pre-start tests failed - the service should not be started.
return 0
}
checkstatus() {
# Returns:
# 0 - Service is running.
# 1 - Service is running, but there is a problem with the .pid file.
# 2 - Service is not running.
# shellcheck disable=SC2155
local RET=0 RUNPIDS="$({ pgrep -f "$SERVICE_EXEC"; pgrep -F "$SERVICE_PIDFILE" 2>/dev/null; } | sort -u)"
if [[ -n "$RUNPIDS" ]]; then
printf "%s: %s: %s" "${BASH_SOURCE[0]##*/}" "status" "service running"
if [[ -n "$SERVICE_PIDFILE" ]]; then
if [[ ! -e "$SERVICE_PIDFILE" ]]; then
printf "%s" ", but .pid file does not exist"
RET=1
elif ! grep "\<$(<"$SERVICE_PIDFILE")\>" <<<"$RUNPIDS" >/dev/null 2>&1; then
printf "%s" ", but .pid file is stale"
RET=1
fi
fi
printf "\\n"
else
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "status" "service stopped"
RET=2
fi
return "$RET"
}
startdaemon() {
# Returns:
# 0 - Service started successfully.
# 1 - Sanity or pre-start check failed.
# 2 - Error code returned when starting service.
local ERR
if [[ ! -e "$SERVICE_EXEC" ]]; then
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "not started - '$SERVICE_EXEC' not found" >&2
return 1
elif [[ ! -x "$SERVICE_EXEC" ]]; then
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "not started - '$SERVICE_EXEC' not executable" >&2
return 1
elif ! checkconfigured; then
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "not started - pre-start checks failed" >&2
return 1
fi
mkdir /run/samba 2>/dev/null
env "${SERVICE_ENV[@]@Q}" "${SERVICE_EXTRA_ENV[@]@Q}" "$SERVICE_EXEC" "${SERVICE_ARGS[@]@Q}" "${SERVICE_EXTRA_ARGS[@]@Q}" >/dev/null 2>&1
ERR=$?
(( ERR != 0 )) && {
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "failed to start service (error code '$ERR)'" >&2
return 2
}
return 0
}
stopdaemon() {
# Returns:
# 0 - The service was stopped sucessfully with a SIGTERM.
# 1 - The service was stopped sucessfully with a SIGKILL.
# 2 - An error occured while stopping service.
local ERR RET=0 T="${SLAY_DELAY:-2}"
kill -TERM "$(pgrep -f "$SERVICE_EXEC" | tr $'\n' ' ')" >/dev/null 2>&1
sleep 0.5
T="$(awk -v T="$T" 'BEGIN {print T - 0.5}')"
checkstatus >/dev/null
ERR=$?
if (( ERR <= 1 )); then
[[ -n "$SERVICE_PIDFILE" ]] && [[ -e "$SERVICE_PIDFILE" ]] && {
kill -TERM "$(<"$SERVICE_PIDFILE")" >/dev/null 2>&1
sleep 0.5
T="$(awk -v T="$T" 'BEGIN {print T - 0.5}')"
checkstatus >/dev/null
ERR=$?
(( ERR <= 1 )) && sleep "$T"
}
elif (( ERR == 0 )); then
if kill -KILL "$({ pgrep -f "$SERVICE_EXEC"; cat "$SERVICE_PIDFILE" 2>/dev/null; } | sort -u | tr $'\n' ' ')" >/dev/null 2>&1; then
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "warning" "failed to stop service gracefully - slayed" >&2
RET=1
else
RET=2
fi
fi
return "$RET"
}
RET=0
case "$1" in
'start')
checkstatus >/dev/null
ERR=$?
if (( ERR <= 1 )); then
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "service running" >&2
printf "%s\\n" "Try: ${BASH_SOURCE[0]} status" >&2
RET=1
elif (( ERR == 2 )); then
startdaemon
ERR=$?
if (( ERR == 1 )); then
RET=3
elif (( ERR == 2 )); then
RET=5
fi
fi
;;
'stop')
checkstatus >/dev/null
ERR=$?
if (( ERR <= 1 )); then
stopdaemon
ERR=$?
(( ERR == 2 )) && {
sleep 0.1
checkstatus >/dev/null
ERR=$?
(( ERR <= 1 )) && {
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "service failed to stop" >&2
RET=5
}
}
elif (( ERR == 2 )); then
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "service stopped" >&2
printf "%s\\n" "Try: ${BASH_SOURCE[0]} status" >&2
RET=1
fi
;;
'restart')
checkstatus >/dev/null
ERR=$?
(( ERR <= 1 )) && {
stopdaemon
ERR=$?
if (( ERR <= 1 )); then
sleep "${RESTART_DELAY:-2}"
RET=-1
elif (( ERR == 2 )); then
sleep 0.1
checkstatus >/dev/null
ERR=$?
(( ERR <= 1 )) && {
printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "error" "service failed to stop" >&2
RET=5
}
fi
}
(( RET <= 0 )) && {
startdaemon
ERR=$?
if (( ERR == 0 )); then
RET=0
elif (( ERR == 1 )); then
RET=3
elif (( ERR == 2 )); then
RET="$(( RET + 5 ))"
fi
}
;;
'status')
checkstatus
ERR=$?
if (( ERR == 1 )); then
RET=4
elif (( ERR == 2 )); then
RET=5
fi
;;
*)
printf "%s\\n" "Usage: ${BASH_SOURCE[0]} <start|stop|restart|status>" >&2
printf "%s\\n" "Error codes:" >&2
printf " %s: %s\\n" "0" "For 'start', 'restart' and 'stop': Requested action succeeded." >&2
printf " %s\\n" "For 'status': Service is running." >&2
printf " %s: %s\\n" "1" "Usage error." >&2
printf " %s: %s\\n" "2" "A general error occurred." >&2
printf " %s: %s\\n" "3" "Sanity or pre-start check failed." >&2
printf " %s: %s\\n" "4" "For 'start', 'restart' and 'stop': Partial failure to complete action." >&2
printf " %s\\n" "For 'status': Service is running, but a problem exists with the .pid file." >&2
printf " %s: %s\\n" "5" "For 'start', 'restart' and 'stop': Total failure to complete action." >&2
printf " %s\\n" "For 'status': Service is not running." >&2
RET=1
;;
esac
exit "$RET"