exit after rsync error

This commit is contained in:
matthias@arch 2022-03-12 01:01:38 +01:00
parent 2f47b4c6af
commit b8c38d85ce

137
msynk.sh
View File

@ -1,15 +1,14 @@
#!/bin/bash #!/bin/bash
# Made by Matthias Quintern # Made by Matthias Quintern
# 02/2022 # 03/2022
# This software comes with no warranty. # This software comes with no warranty.
# This software is licensed under the GPL3
# ABOUT # ABOUT
# Synchronizes files from a sender to a receiver using rsync # Synchronizes files from a sender to a receiver using rsync
# The files can be encrypted before or decrypted after the transfer using the mkrypt script # The files can be encrypted before or decrypted after the transfer using the mkrypt script
#
# SETTINGS # SETTINGS
#
# The directory that is searched for config files # The directory that is searched for config files
CONFIG_DIR=~/.config/msynk/ CONFIG_DIR=~/.config/msynk/
# When using encrypt/decrypt, the source is en/decrypted to TMP_DIR and then rsynced to receiver from there # When using encrypt/decrypt, the source is en/decrypted to TMP_DIR and then rsynced to receiver from there
@ -22,7 +21,7 @@ mkrypt=/usr/bin/mkrypt
# Additional flags for mkrypt # Additional flags for mkrypt
mkrypt_flags= mkrypt_flags=
rsync_flags=(-ruvh) rsync_flags=(-ruh)
# rsync_flags+=(--rsh="ssh -p 69") # rsync_flags+=(--rsh="ssh -p 69")
# r - relative # r - relative
# v - verbose # v - verbose
@ -33,15 +32,15 @@ rsync_flags=(-ruvh)
# see "man rsync" for more # see "man rsync" for more
#
# UTILITY # UTILITY
#
FMT_MESSAGE="\e[1;34m%s\e[0m\n" FMT_MESSAGE="\e[1;34m%s\e[0m\n"
FMT_ERROR="\e[1;31mERROR: \e[0m%s\n" FMT_ERROR="\e[1;31mERROR: \e[0m%s\n"
FMT_SYNC="\e[1;32m:Syncing\e[0m %s\n" FMT_SYNC="\e[1;32mSyncing: \e[0m%s\n"
# FMT_UPDATE="\e[1;33mUpdating:\e[0m %s\n"
FMT_CONFIG="\e[34m%s\e:\t\e[1;33m%s\e[0m\n" FMT_CONFIG="\e[34m%s\e:\t\e[1;33m%s\e[0m\n"
FMT_CMD="\e[1;33mRunning: \e[0m%s\n"
# FUNCTIONS
# silence commands
quiet() { "$@" > /dev/null 2>&1; } quiet() { "$@" > /dev/null 2>&1; }
# check if a passed parameter is contained in file # check if a passed parameter is contained in file
@ -59,9 +58,7 @@ check_path_in_args()
} }
# # SYNC SENDER TO RECEIVER
# sync sender to receiver
#
sync_sender_to_receiver() sync_sender_to_receiver()
{ {
# perform a dry run to see which files would be deleted # perform a dry run to see which files would be deleted
@ -97,7 +94,7 @@ sync_sender_to_receiver()
dest=$receiver$(basename $path) dest=$receiver$(basename $path)
elif [[ -f $path ]]; then elif [[ -f $path ]]; then
dest=$receiver dest=$receiver
elif [[ $sender == *@*:* ]]; then # if sender is remote, assume the path is a dir if it has a slash and a file otherwise elif [[ $sender == *:* ]]; then # if sender is remote, assume the path is a dir if it has a slash and a file otherwise
[[ $path == *"/" ]] && dest=$receiver$(basename $path) || dest=$receiver [[ $path == *"/" ]] && dest=$receiver$(basename $path) || dest=$receiver
else else
printf "$FMT_ERROR" "Invalid path: $path"; exit 1 printf "$FMT_ERROR" "Invalid path: $path"; exit 1
@ -108,57 +105,67 @@ sync_sender_to_receiver()
if [[ -n $encrypt ]]; then if [[ -n $encrypt ]]; then
[[ -f $path ]] && tmp_source=$TMP_DIR$(basename $path).gpg [[ -f $path ]] && tmp_source=$TMP_DIR$(basename $path).gpg
[[ $v -ge 3 ]] && printf "$FMT_CMD" "bash $mkrypt --encrypt $path --output $TMP_DIR $mkrypt_flags" [[ $v -ge 3 ]] && printf "$FMT_CMD" "bash $mkrypt --encrypt $path --output $TMP_DIR $mkrypt_flags"
bash $mkrypt --encrypt $path --output $TMP_DIR $mkrypt_flags || exit 1 bash $mkrypt --encrypt $path --output $TMP_DIR $mkrypt_flags || exit 3
[[ $v -ge 3 ]] && printf "$FMT_CMD" "rsync ${rsync_flags[@]} $tmp_source $dest" [[ $v -ge 3 ]] && printf "$FMT_CMD" "rsync ${rsync_flags[*]} $tmp_source $dest"
rsync "${rsync_flags[@]}" $tmp_source $dest rsync ${rsync_flags[*]} $tmp_source $dest || { printf "$FMT_ERROR" "rsync exited with exit code $?"; exit 2; }
else else
[[ -f $path ]] && tmp_source=$TMP_DIR$(basename $path) [[ -f $path ]] && tmp_source=$TMP_DIR$(basename $path)
[[ $v -ge 3 ]] && printf "$FMT_CMD" "rsync ${rsync_flags[@]} $path $TMP_DIR" [[ $v -ge 3 ]] && printf "$FMT_CMD" "rsync ${rsync_flags[*]} $path $TMP_DIR"
rsync "${rsync_flags[@]}" $path $TMP_DIR rsync ${rsync_flags[*]} $path $TMP_DIR || { printf "$FMT_ERROR" "rsync exited with exit code $?"; exit 2; }
[[ $v -ge 3 ]] && printf "$FMT_CMD" "bash $mkrypt --decrypt $tmp_source --output $(readlink -f $dest) $mkrypt_flags" [[ $v -ge 3 ]] && printf "$FMT_CMD" "bash $mkrypt --decrypt $tmp_source --output $(readlink -f $dest) $mkrypt_flags"
bash $mkrypt --decrypt $tmp_source --output $(readlink -f $dest) $mkrypt_flags || exit 1 bash $mkrypt --decrypt $tmp_source --output $(readlink -f $dest) $mkrypt_flags || exit 3
fi fi
else else
printf "$FMT_CMD" "rsync ${rsync_flags[@]} $delete $path $dest" [[ $v -ge 3 ]] && printf "$FMT_CMD" "rsync ${rsync_flags[*]} $delete $path $dest"
rsync "${rsync_flags[@]}" $delete $path $dest rsync ${rsync_flags[*]} $delete $path $dest || { printf "$FMT_ERROR" "rsync exited with exit code $?"; exit 2; }
fi fi
[[ $TMP_DIR == *msynk* ]] && { [[ $TMP_DIR == *msynk* ]] && {
rm -rf $TMP_DIR/* || { printf "$FMT_ERROR" "Can not delete \$TMP_DIR: $TMP_DIR"; exit 1; } rm -rf $TMP_DIR/* || { printf "$FMT_ERROR" "Can not delete \$TMP_DIR: $TMP_DIR"; exit 1; }
} || { printf "$FMT_ERROR" "Will not delete \$TMP_DIR because it might be dangerous (path does not contain 'msynk'): $TMP_DIR"; exit 1; } } || { printf "$FMT_ERROR" "Will not delete \$TMP_DIR because it might be dangerous (path does not contain 'msynk'): $TMP_DIR"; exit 1; }
done done
# put todays date in the config
if [[ -f $CONFIG_DIR/$config ]]; then
if grep -xq "date=.*" $CONFIG_DIR$config; then
[[ $v -ge 2 ]] && printf "$FMT_MESSAGE" "Updating date in $CONFIG_DIR$config."
sed "s/date=.*/date=\"$(date)\"/" $CONFIG_DIR$config -i
else
[[ $v -ge 2 ]] && printf "$FMT_MESSAGE" "Writing current date to $CONFIG_DIR$config."
echo "date=\"$(date)\"" >> $CONFIG_DIR$config
fi
fi
[[ $v -ge 2 ]] && printf "$FMT_MESSAGE" "Running 'sync' to write cached writes to persistent storage" [[ $v -ge 2 ]] && printf "$FMT_MESSAGE" "Running 'sync' to write cached writes to persistent storage"
sync sync
[[ $v -ge 1 ]] && printf "$FMT_MESSAGE" "Done!" [[ $v -ge 1 ]] && printf "$FMT_MESSAGE" "Done!"
} }
#
# HELP # HELP
#
show_help() show_help()
{ {
printf "\e[33mArgument Short Action:\e[0m printf "\e[33mArgument Short Action:\e[0m
--help -h show this --help -h Show this.
--settings -s show current settings --settings -s Show current settings.
--config [name] -c use sender, receiver, paths from config file with [name] --config [name] -c Use sender, receiver, paths from config file with [name].
--sender [path] -s sender directory, with trailing slash! Defaults to the current working directory --sender [path] -s Sender directory, with trailing slash! Defaults to the current working directory.
--receiver [path] -r receiver directory, with trailing slash! --receiver [path] -r Receiver directory, with trailing slash!.
--reverse swap receiver and sender --reverse Swap receiver and sender.
--encrypt encrypt files before syncing --encrypt Encrypt files before syncing.
--decrypt decrypt files before syncing --decrypt Decrypt files before syncing.
--mkrypt-flags [flags] additional flags for mkrypt --date Only process files that have been modified since the program was last run. Needs -c and (--encrypt/--decrypt).
--mkrypt-flags [flags] Additional flags for mkrypt.
--delete -d delete files that exist on receiver, but not on sender --delete -d Delete files that exist on receiver, but not on sender. Does not work with --encrypt/--decrypt.
--skip-dryrun delete without asking first --skip-dryrun Delete without asking first.
--rsync-flags [flags] additional flags for rsync --rsync-flags [flags] Additional flags for rsync.
--verbose -v increase verbosity --verbose -v Increase verbosity.
--silent decrease verbosity --silent Decrease verbosity.
--debug maximum verbosity --debug Maximum verbosity.
Positional arguments are: Positional arguments are:
- if using a config: a string that must be in the configs paths: eg. 'foo' will include ~/foo but nor ~/bar - if using a config: a string that must be in the configs paths: eg. 'foo' will include ~/foo but nor ~/bar
@ -169,27 +176,26 @@ See the manpage for more information.
} }
# SETTINGS
show_settings() show_settings()
{ {
printf "\e[1mThe current settings are:\e[0m\n" printf "\e[1mThe current settings are:\e[0m\n"
printf "$FMT_CONFIG" "\$TMP_DIR " "$TMP_DIR"
printf "$FMT_CONFIG" "\$TMP_FILE " "$TMP_FILE" printf "$FMT_CONFIG" "\$TMP_FILE " "$TMP_FILE"
printf "$FMT_CONFIG" "\$CONFIG_DIR " "$CONFIG_DIR"
[[ -f $mkrypt ]] || mkrypt_installed="(file not found)"
printf "$FMT_CONFIG" "\$mkrypt " "$mkrypt $mkrypt_installed"
printf "$FMT_CONFIG" "\$rsync_flags " "${rsync_flags[*]}" printf "$FMT_CONFIG" "\$rsync_flags " "${rsync_flags[*]}"
} }
#
# PARSE ARGS # PARSE ARGS
#
if [ -z $1 ]; then if [ -z $1 ]; then
show_help show_help
exit 0 exit 0
fi fi
all=1
all=0
BACKUP=1 # use if the script gets more functions later
# all command line args with no "-" are interpreted as part of filepaths.
paths_2=() paths_2=()
while (( "$#" )); do while (( "$#" )); do
case "$1" in case "$1" in
@ -219,9 +225,11 @@ while (( "$#" )); do
shift ;; shift ;;
--encrypt) --encrypt)
encrypt=1 encrypt=1
use_encryption=1
shift ;; shift ;;
--decrypt) --decrypt)
decrypt=1 decrypt=1
use_encryption=1
shift;; shift;;
-d|--delete) -d|--delete)
delete=--delete delete=--delete
@ -234,6 +242,9 @@ while (( "$#" )); do
rsync_flags+=("${2}") rsync_flags+=("${2}")
shift 2 shift 2
else printf "$FMT_ERROR" "Missing argument for $1"; exit 1; fi ;; else printf "$FMT_ERROR" "Missing argument for $1"; exit 1; fi ;;
--date)
use_date=1
shift ;;
--msynk-flags) --msynk-flags)
if [[ -n ${2} ]]; then # && "${2:0:1}" != "-" ]]; then # possibly problematic if $2 is an msynk flag if [[ -n ${2} ]]; then # && "${2:0:1}" != "-" ]]; then # possibly problematic if $2 is an msynk flag
mkrypt_flags+=("${2}") mkrypt_flags+=("${2}")
@ -263,14 +274,23 @@ while (( "$#" )); do
esac esac
done done
# PREPARATION & CHECKS
# check if rsync is installed # check if rsync is installed
if ! command -v rsync &> /dev/null; then if ! command -v rsync &> /dev/null; then
printf "$FMT_ERROR" "rsync is not installed." printf "$FMT_ERROR" "rsync is not installed."
exit 1
fi fi
# if using encryption, check if mkrypt is installed
[[ $use_encryption = 1 && ! -f $mkrypt ]] && printf "$FMT_ERROR" "Can not use encryption: mkrypt is not installed at given path: $mkrypt."
# if using a config # if using a config
if [[ -n $config ]]; then if [[ -n $config ]]; then
bash $CONFIG_DIR/$config || { printf "$FMT_ERROR" "Error running the config file: $CONFIG_DIR/$config"; exit 1; } source $CONFIG_DIR$config || { printf "$FMT_ERROR" "Error running the config file: $CONFIG_DIR/$config"; exit 1; }
if [[ $use_encryption = 1 ]]; then
[[ -z $reverse ]] && encrypt=1 || decrypt=1
fi
[[ $v -ge 3 ]] && printf "$FMT_MESSAGE" "Loaded config: $CONFIG_DIR$config:: date:$date sender:$sender receiver:$receiver use_encryption:$use_encryption encrypt:$encrypt decrypt:$decrypt paths:${paths[*]}"
fi fi
# overwrite stuff from the config if anything else was given / set variables of no config was given # overwrite stuff from the config if anything else was given / set variables of no config was given
@ -288,23 +308,19 @@ if [[ -n $reverse ]]; then
receiver=$tmp_sender receiver=$tmp_sender
fi fi
# make sure sender is absolute with slash
wd=$PWD
# quiet cd $sender && sender="$PWD/" || { printf "$FMT_ERROR" "Sender directory does not exist: $sender"; exit 1; }
# make sure reveiver is absolute
# cd $wd
# mkdir -p $receiver || { printf "$FMT_ERROR" "Can not create config dir: $receiver"; exit 1; }
# quiet cd $receiver && receiver="$PWD/" || { printf "$FMT_ERROR" "Receiver directory does not exist: $receiver"; exit 1; }
# make sure receiver has trailing slash # make sure receiver has trailing slash
[[ $receiver != *"/" ]] && receiver=$receiver"/" [[ $receiver != *"/" ]] && receiver=$receiver"/"
# create receiver dir if its local
[[ ! $receiver == *:* ]] && { mkdir -p $receiver || { printf "$FMT_ERROR" "Can not create receiver directory: $receiver"; exit 1; }}
echo "sender:$sender rec:$receiver paths=$paths paths2=$paths_2" [[ $v -ge 3 ]] && printf "$FMT_MESSAGE" "sender:$sender receiver:$receiver paths:$paths paths_2:$paths_2"
# filter paths: # filter paths:
# - if using config: all paths from config that have a pos.arg in them # - if using config: all paths from config that have a pos.arg in them
# - else: pos.args, must be relative to specified --sender # - else: pos.args, must be relative to specified --sender
filtered_paths=() filtered_paths=()
if [[ -n $config ]]; then if [[ -n $config ]]; then
[[ $sender != *"/" ]] && sender=$sender"/"
for path in ${paths[@]}; do for path in ${paths[@]}; do
if check_path_in_args; then if check_path_in_args; then
filtered_paths+=($sender$path) filtered_paths+=($sender$path)
@ -312,20 +328,23 @@ if [[ -n $config ]]; then
done done
else else
for path in ${paths_2[@]}; do # add slash if directory for path in ${paths_2[@]}; do # add slash if directory
# quiet cd $sender
[[ -d $path ]] && [[ $path != *"/" ]] && path=$path"/" [[ -d $path ]] && [[ $path != *"/" ]] && path=$path"/"
# quiet cd $sender && quiet cd $path && filtered_paths+=($PWD/) || {
# quiet cd $sender && ls -d $path && filtered_paths+=($PWD/$path)
# }
filtered_paths+=($sender$path) filtered_paths+=($sender$path)
done done
fi fi
cd $wd [[ $v -ge 3 ]] && printf "$FMT_MESSAGE" "Filtered paths: ${filtered_paths[@]}"
echo "FPaths: ${filtered_paths[@]}"
# sanity checks # sanity checks
[[ -z $filtered_paths ]] && { printf "$FMT_ERROR" "Missing valid paths."; exit 1; } [[ -z $filtered_paths ]] && { printf "$FMT_ERROR" "Missing valid paths."; exit 1; }
[[ -z $receiver ]] && { printf "$FMT_ERROR" "Missing receiver. Specifiy with --receiver"; exit 1; } [[ -z $receiver ]] && { printf "$FMT_ERROR" "Missing receiver. Specifiy with --receiver"; exit 1; }
# if using --date
if [[ -n $use_date && -z $date ]]; then # if --date but date is not set, use 0 (unix time)
[[ $v -ge 1 ]] && printf "$FMT_MESSAGE" "--date passed but date not set in config, using 0 (unix time)"
date=$(date -d @0)
fi
[[ -n $use_date ]] && mkrypt_flags+=("--date \"${date}\"")
# RUN!
sync_sender_to_receiver sync_sender_to_receiver
exit 0 exit 0