#!/bin/bash # Version: 0.3.0-rsync # Copyright (c) 2005-2022: # Darren 'Tadgy' Austin # Licensed under the terms of the GNU General Public License version 3. # shellcheck disable=SC2016,SC2034 RSYNC_EXEC="/usr/bin/rsync" RSYNC_ARGS=('--daemon' '${RSYNC_CONF:---config=/etc/rsyncd/rsyncd.conf}') RSYNC_PIDFILE="/run/rsyncd.pid" DAEMON_EXEC="/usr/bin/daemon" DAEMON_ARGS=('-N' '-n' "lumberjack-${0##*rc.}" '-r' '-a' '60' '-A' '5' '-L' '1800' '-M' '3' '-l' 'daemon.err' '-b' 'daemon.debug' '-o' 'daemon.info' '--') LUMBERJACK_EXEC="/opt/bin/lumberjack" LUMBERJACK_ARGS=('-u' '${LUMBERJACK_RUNUSER:-logger}' '-z' '-r' '-i' '${LUMBERJACK_SOCK:-/run/rsyncd-log.sock}' '-o' '${LUMBERJACK_RUNUSER:-logger}:mirror' '-mp' '006' '-l' 'logs/rsyncd-transfers.log' '${LUMBERJACK_BASEDIR:-/data/sites/slackware.uk}' 'logs/%Y/%m/rsyncd-transfers.log') LUMBERJACK_RUNUSER="logger" LUMBERJACK_SOCK="/run/rsyncd-log.sock" LUMBERJACK_BASEDIR="/data/sites/slackware.uk" # Allow configuration in /etc/default to override. # Additional available variables: # RSYNC_ENVIRONMENT=() # Extra environment passed to $RSYNC_EXEC. Must be an array. # RSYNC_CONF="" # Path to the config file for RSYNC_EXEC. Default: /etc/rsyncd/rsyncd.conf. # DAEMON_ENVIRONMENT=() # Extra environment passed to $DAEMON_EXEC. Must be an array. # LUMBERJACK_RUNUSER="" # Username to run lumberjack as. Default: logger. # LUMBERJACK_SOCK="" # Location of the socket for lumberjack to read data. Default: /run/rsyncd-log.sock. # LUMBERJACK_BASEDIR="" # The base directory where lumberjack should write logs. Default: /data/sites/slackware.uk. # 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. # shellcheck disable=SC1090 [[ -e "/etc/default/${0##*rc.}" ]] && { source "/etc/default/${0##*rc.}" || return 1 2>/dev/null || exit 1; } # Now all possible variable changes are complete, expand out the embedded variables. eval "$(declare -p RSYNC_ARGS | sed -re 's/\\\$/$/g')" eval "$(declare -p LUMBERJACK_ARGS | sed -re 's/\\\$/$/g')" error() { printf "%s: %s\\n" "${BASH_SOURCE[0]##*/}" "$*" >&2 } checkconfigured() { # 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. A return value of 0 means the # tests were passed and the daemon should be started. Any other value prevents the # daemon from being started, and an error message will be emitted. id "${LUMBERJACK_RUNUSER:-logger}" >/dev/null 2>&1 || return 1 [[ ! -e "${LUMBERJACK_BASEDIR:-/data/sites/slackware.uk}" ]] && return 1 [[ ! -d "${LUMBERJACK_BASEDIR:-/data/sites/slackware.uk}" ]] && return 1 [[ ! -e "${RSYNC_CONF:-/etc/rsyncd/rsyncd.conf}" ]] && return 1 return 0 } checkstatus() { # shellcheck disable=SC2155 local RET=0 RUNPIDS="$({ pgrep -f "$RSYNC_EXEC"; pgrep -F "$RSYNC_PIDFILE" 2>/dev/null; } | sort -u )" if "$DAEMON_EXEC" --running -n "lumberjack-${0##*rc.}"; then printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "${LUMBERJACK_EXEC##*/}" "running" else printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "${LUMBERJACK_EXEC##*/}" "stopped" RET=1 fi if [[ -n "$RUNPIDS" ]]; then printf "%s: %s: %s" "${BASH_SOURCE[0]##*/}" "${RSYNC_EXEC##*/}" "running" if [[ -n "$RSYNC_PIDFILE" ]]; then if [[ ! -e "$RSYNC_PIDFILE" ]]; then printf "%s" ", but .pid file does not exist" elif ! grep "\<$(<"$RSYNC_PIDFILE")\>" <<<"$RUNPIDS" >/dev/null 2>&1; then printf "%s" ", but .pid file is stale" fi fi printf "\\n" else printf "%s: %s: %s\\n" "${BASH_SOURCE[0]##*/}" "${RSYNC_EXEC##*/}" "stopped" RET=$(( RET + 2)) fi return $RET } startdaemon() { checkconfigured || { error "${RSYNC_EXEC##*/}: not started - pre-start checks failed" return 2 } # shellcheck disable=SC2048,SC2086 ${DAEMON_ENVIRONMENT:+declare ${DAEMON_ENVIRONMENT[*]};} "$DAEMON_EXEC" ${DAEMON_ARGS[*]} "$LUMBERJACK_EXEC" ${LUMBERJACK_ARGS[*]} # shellcheck disable=SC2181 (( $? != 0 )) && { error "error starting '${DAEMON_EXEC##*/}'" return 2 } # shellcheck disable=SC2048,SC2086 ${RSYNC_ENVIRONMENT:+declare ${RSYNC_ENVIRONMENT[*]};} "$RSYNC_EXEC" ${RSYNC_ARGS[*]} # shellcheck disable=SC2181 if (( $? != 0 )); then error "error starting '${RSYNC_EXEC##*/}'" return 2 else return 0 fi } stopdaemon() { kill -TERM "$(pgrep -f "$RSYNC_EXEC" | tr $'\n' ' ')" >/dev/null 2>&1 [[ -e "$RSYNC_PIDFILE" ]] && { sleep 0.5 kill -TERM "$(<"$RSYNC_PIDFILE")" >/dev/null 2>&1 } sleep "${SLAY_DELAY:-2}" checkstatus >/dev/null && { error "${RSYNC_EXEC##*/}: failed to stop gracefully - slaying" kill -KILL "$({ cat "$RSYNC_PIDFILE"; pgrep -f "$RSYNC_EXEC"; } 2>/dev/null | sort -u | tr $'\n' ' ')" >/dev/null 2>&1 } sleep 0.5 "$DAEMON_EXEC" -n "lumberjack-${0##*rc.}" --stop 2>/dev/null sleep "${SLAY_DELAY:-2}" checkstatus >/dev/null && { error "${DAEMON_EXEC##*/}: failed to stop gracefully - slaying" "$DAEMON_EXEC" -n "lumberjack-${0##*rc.}" --signal=kill 2>/dev/null } return 0 } for EXEC in "$RSYNC_EXEC" "$DAEMON_EXEC" "$LUMBERJACK_EXEC"; do [[ ! -e "$EXEC" ]] && { error "$EXEC: not found" return 1 2>/dev/null || exit 1 } [[ ! -x "$EXEC" ]] && { error "$EXEC: not executable" return 1 2>/dev/null || exit 1 } done case "$1" in 'start') checkstatus >/dev/null ERR=$? if (( ERR == 3 )); then startdaemon RET=$? elif (( ERR == 2 )); then error "${DAEMON_EXEC##*/}: already running" error "${RSYNC_EXEC##*/}: stopped" printf " %s\\n" "Try: ${BASH_SOURCE[0]} restart" >&2 RET=1 elif (( ERR == 1 )); then error "${DAEMON_EXEC##*/}: stopped" error "${RSYNC_EXEC##*/}: already running" printf " %s\\n" "Try: ${BASH_SOURCE[0]} restart" >&2 RET=1 else error "${DAEMON_EXEC##*/}: already running" error "${RSYNC_EXEC##*/}: already running" printf " %s\\n" "Try: ${BASH_SOURCE[0]} status" >&2 RET=1 fi ;; 'stop') checkstatus >/dev/null if (( $? == 3 )); then error "${DAEMON_EXEC##*/}: not running" error "${RSYNC_EXEC##*/}: not running" printf " %s\\n" "Try: ${BASH_SOURCE[0]} status" >&2 RET=1 else stopdaemon RET=$? fi ;; 'restart') checkstatus >/dev/null (( $? != 3 )) && { stopdaemon >/dev/null 2>&1 sleep "${RESTART_DELAY:-2}" } startdaemon RET=$? ;; 'status') checkstatus RET=$? ;; *) printf "%s\\n" "Usage: ${BASH_SOURCE[0]} " >&2 RET=1 ;; esac return $RET 2>/dev/null || exit $RET