#!/bin/sh set -eu umask 022 LOCKFILE="/var/run/sync-mirrors/lockfile" LOGFILE="/var/log/sync-mirrors/sync-mirrors-$(date +%Y%m%d%H%M%S).log" CONFDIR="/etc/sync-mirrors" usage() { echo "Usage: $(basename "$0") [-v] [mirror]" 1>&2 echo " $(basename "$0") -l" 1>&2 } list_mirrors() { for f in "$CONFDIR"/*.conf ; do basename "$f" ".conf" done } logmsg() { "$VERBOSE" && echo "$1" echo "$(date '+%Y/%m/%d %H:%M:%S') [$$] $1" >> "$LOGFILE" } logstream() { while read -r line; do logmsg "$line" done } if [ ! -d "$CONFDIR" ]; then echo "ERR: Config directory [${CONFDIR}] missing" 1>&2 exit 1 fi VERBOSE=false NOOP="" EXTRA_OPTS="" while getopts "vhln" c ; do case $c in v) VERBOSE=true EXTRA_OPTS="${EXTRA_OPTS} -v --progress" ;; h) usage exit 0 ;; l) echo "Available mirrors:" list_mirrors | sed -e 's/^/ /' exit 0 ;; n) NOOP=" (DRY RUN)" EXTRA_OPTS="${EXTRA_OPTS} -n" ;; *) usage exit 1 ;; esac done shift "$((OPTIND - 1))" if [ $# -eq 0 ]; then set -- $(list_mirrors) if [ $# -eq 0 ]; then echo "ERR: No configured mirrors found" 1>&2 exit 1 fi else for mirror in "$@" ; do if [ ! -f "${CONFDIR}/$1.conf" ]; then echo "ERR: No mirror named [$1]" 1>&2 exit 1 fi done fi if [ "$(whoami)" != "mirror" ]; then echo "ERR: Script needs to be run as mirror user" 1>&2 exit 1 fi if [ -f "$LOCKFILE" ]; then if kill -0 "$(cat $LOCKFILE)" ; then STARTED=" ($(stat --format='%y' $LOCKFILE))" echo "ERR: Lockfile exists${STARTED}, exiting" 1>&2 exit 1 else echo "WARN: Removing stale lock file..." 1>&2 rm -f "$LOCKFILE" fi fi trap 'rm -f $LOCKFILE' INT TERM EXIT echo "$$" > "$LOCKFILE" for mirror in "$@" ; do POSTCMD="" SRC="" RSYNCOPTS="" # shellcheck source=/dev/null . "${CONFDIR}/${mirror}.conf" if [ "$SRC" = "" ]; then echo "ERR: No SRC set for mirror ${mirror} ..." 1>&2 exit 1 fi logmsg "Starting ${mirror} sync${NOOP}..." rsync -aH -4 $EXTRA_OPTS --numeric-ids --delete --delete-delay \ --delay-updates --no-motd $RSYNCOPTS --log-file="$LOGFILE" \ --exclude=.~tmp~/ "$SRC" "/srv/mirrors/${mirror}/" STATUS=$? if [ $STATUS -ne 0 ]; then echo "WARN: Encountered errors on ${mirror} sync, see ${LOGFILE} for details" 1>&2 fi logmsg "Finished ${mirror} sync with exit status ${STATUS}${NOOP} ..." if [ "$POSTCMD" != "" ]; then logmsg "Running post for ${mirror} ..." $POSTCMD 2>&1 | logstream logmsg "Finished post for ${mirror} ..." fi done