From e8af0d6d6890846e1a0f215bd0a5aa4a916dbba4 Mon Sep 17 00:00:00 2001 From: Frank Brehm Date: Mon, 21 Oct 2024 14:15:44 +0200 Subject: [PATCH] Adding share/sync-share.sh --- share/sync-share.sh | 284 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 284 insertions(+) create mode 100755 share/sync-share.sh diff --git a/share/sync-share.sh b/share/sync-share.sh new file mode 100755 index 0000000..f452df7 --- /dev/null +++ b/share/sync-share.sh @@ -0,0 +1,284 @@ +#/bin/bash + +set -e +set -u + +BASE_NAME="$( basename ${0} )" +MY_REAL_NAME=$( readlink -f $0 ) + +if [[ -f /usr/libexec/pixelpark/functions.rc ]] ; then + . /usr/libexec/pixelpark/functions.rc +else + echo "Did not found /usr/libexec/pixelpark/functions.rc." >&2 + exit 5 +fi + +SRC_ROOT=/mnt/emc +TGT_ROOT=/srv/nfs +NO_OWNER= +REMOVE_SUPER= + +SHARE_BASE= +SRC_DIR= +TGT_DIR= + +BWLIMIT=20M + +detect_color + +set_locale "en_US.utf8" + +DESCRIPTION=$( cat <<-EOF + Syncing an EMC share below '${SRC_ROOT}/' to '${TGT_ROOT}/'. + + EOF +) + +#------------------------------------------------------------------------------ +usage() { + cat <<-EOF + Usage: ${BASE_NAME} [Common Options] [-N|--no-owner] [-R|--remove-super-bit] [--bwlimit BWLIMIT] SHARE + ${BASE_NAME} [-h|--help] + ${BASE_NAME} [-V|--version] + + Mandatory Parameter: + SHARE The basename of the directory below ''${SRC_ROOT}', where the EMC share is mounted. + + Special Options: + -N|--no-owner Don't sync the owners and the groups of the source share to the target + files and directories. + -R|--remove-super-bit + Remove the super bits (Set-UID bit, Set-GID bit and sticky bit) from the files + and directories in the target directory after syncing from source. + --bwlimit BWLIMIT + Limiting the socket I/O bandwith to this value. Set to an empty string + to disabling bandwith limiting. For syntax, see 'man rsync'. + Default value: '${BWLIMIT}'. + + Common Options: + ${STD_USAGE_MSG} + EOF + +} + +#------------------------------------------------------------------------------ +get_options() { + + local tmp= + local base_dir= + + set +e + tmp=$( getopt -o "NR${STD_SHORT_OPTIONS}" \ + --long "no-owner,remove-super-bit,bwlimit:,${STD_LONG_OPTIONS}" \ + -n "${BASE_NAME}" -- "$@" ) + if [[ $? != 0 ]] ; then + echo "" >&2 + usage >&2 + exit 1 + fi + set -e + + # Note the quotes around `$TEMP': they are essential! + eval set -- "${tmp}" + eval_common_options "$@" + if [[ "${DEBUG}" == 'y' ]] ; then + declare -p REMAINING_OPTS + declare -p REMAINING_ARGS + fi + + local len="${#REMAINING_OPTS[*]}" + local i="0" + local j= + while [[ "$i" -lt "${len}" ]] ; do + + arg="${REMAINING_OPTS[$i]}" + + case "${arg}" in + -N|--no-owner) + NO_OWNER="y" + i=$(( $i + 1 )) + ;; + -R|--remove-super-bit) + REMOVE_SUPER="y" + i=$(( $i + 1 )) + ;; + --bwlimit) + j=$(( $i + 1 )) + BWLIMIT="${REMAINING_OPTS[$j]}" + i=$(( $i + 2 )) + ;; + *) echo -e "Internal error - option '${RED}${arg}${NORMAL}' was wrong!" + exit 1 + ;; + esac + + done + + if [[ "${#REMAINING_ARGS[@]}" == "0" ]] ; then + error "No share name given to sync." + echo >&2 + usage >&2 + exit 1 + fi + + unset REMAINING_ARGS[0] + if [[ "${DEBUG}" == 'y' ]] ; then + declare -p REMAINING_ARGS + fi + + if [[ "${#REMAINING_ARGS[@]}" -gt '1' ]] ; then + error "Please give only one share to sync." + echo >&2 + usage >&2 + exit 1 + fi + + local given_share + given_share=$( echo "${REMAINING_ARGS[1]}" | sed -e 's|/*$||' ) + if [[ -z "${given_share}" ]] ; then + error "Invalid share name '${RED}${REMAINING_ARGS[1]}${NORMAL}' given." + echo >&2 + usage >&2 + exit 1 + fi + + if [[ "${given_share}" =~ '/' ]] ; then + if [[ "${given_share}" =~ ^${SRC_ROOT}/[^/]*$ ]] ; then + SHARE_BASE=$( basename "${given_share}" ) + else + error "Invalid share name '${RED}${given_share}${NORMAL}' given." + echo >&2 + usage >&2 + exit 1 + fi + else + SHARE_BASE="${given_share}" + fi + + SRC_DIR="${SRC_ROOT}/${SHARE_BASE}" + TGT_DIR="${TGT_ROOT}/${SHARE_BASE}" + +} + +#------------------------------------------------------------------------------ +check_preferences() { + + local has_failure + has_failure= + + if [[ ! -d "${SRC_DIR}" ]] ; then + error "Source directory '${RED}${SRC_DIR}${NORMAL}' does not exists." + has_failure="y" + fi + + if [[ ! -d "${TGT_DIR}" ]] ; then + error "Target directory '${RED}${TGT_DIR}${NORMAL}' does not exists." + has_failure="y" + fi + + if grep -q -w "${SRC_DIR}" /proc/mounts ; then + : + else + error "Source directory '${RED}${SRC_DIR}${NORMAL}' is not mounted." + has_failure="y" + fi + + if [[ "${has_failure}" ]] ; then + exit 2 + fi + +} + +#------------------------------------------------------------------------------ +do_sync() { + + local cmd + cmd="rsync --recursive --links --perms --times --devices --specials --hard-links --atimes" + if [[ -z "${NO_OWNER}" ]] ; then + cmd+=" --owner --group" + fi + if [[ "${VERBOSE}" == "y" ]] ; then + cmd+=" --verbose --progress" + fi + if [[ "${QUIET}" == "y" ]] ; then + cmd+=" --quiet" + else + cmd+=" --stats" + fi + if [[ -n "${BWLIMIT}" ]] ; then + cmd+=" --bwlimit=${BWLIMIT}" + fi + cmd+=" --delete --delete-after \"${SRC_DIR}/\" \"${TGT_DIR}/\"" + + empty_line + info "Syncing from '${CYAN}${SRC_DIR}${NORMAL}' => '${CYAN}${TGT_DIR}${NORMAL}'." + empty_line + + if [[ "${SIMULATE}" == "y" ]] ; then + info "Simulate executing: ${cmd}" + else + debug "Executing: ${cmd}" + eval ${cmd} + fi + +} + +#------------------------------------------------------------------------------ +remove_super() { + + if [[ -z "${REMOVE_SUPER}" ]] ; then + return + fi + + local cmd + + empty_line + info "Removing super bits from directories ..." + cmd="find \"${TGT_DIR}/\" -type d -print0 | xargs -r --null chmod" + if [[ "${VERBOSE}" == "y" ]] ; then + cmd+=" --changes" + fi + cmd+=" a-s" + if [[ "${SIMULATE}" == "y" ]] ; then + info "Simulate executing: ${cmd}" + else + debug "Executing: ${cmd}" + eval ${cmd} + fi + + empty_line + info "Removing super bits from files ..." + cmd="find \"${TGT_DIR}/\" -type f -print0 | xargs -r --null chmod" + if [[ "${VERBOSE}" == "y" ]] ; then + cmd+=" --changes" + fi + cmd+=" a-s" + if [[ "${SIMULATE}" == "y" ]] ; then + info "Simulate executing: ${cmd}" + else + debug "Executing: ${cmd}" + eval ${cmd} + fi + +} + +#------------------------------------------------------------------------------ +main() { + + get_options "$@" + + check_preferences + local start_time=$( my_date ) + do_sync + remove_super + + empty_line + info "${CYAN}Finished${NORMAL} (Started: ${start_time})." + +} + +main "$@" + +exit 0 + +# vim: tabstop=4 expandtab shiftwidth=4 softtabstop=4 list -- 2.39.5