Skip to content

Instantly share code, notes, and snippets.

@Alveel
Last active September 10, 2024 12:23
Show Gist options
  • Save Alveel/c5e2cea553a30c785de91cf5e12201ec to your computer and use it in GitHub Desktop.
Save Alveel/c5e2cea553a30c785de91cf5e12201ec to your computer and use it in GitHub Desktop.
script to run rclone bisync in the background as a cronjob or systemd timer, sending a notification to the user if something goes wrong
#!/usr/bin/env bash
#
# This script runs rclone bisync between two paths and sends a notification to
# the user if something goes wrong with notify-send.
# It is intended to run frequently with a cronjob or systemd user timer.
#
# rclone-bisync path1 path2 [--resync] [--verbose] [--dry-run]
#
verbose=false
path1=""
path2=""
bisync_args=(
--check-access \
--compare size,modtime,checksum \
--download-hash \
--conflict-resolve path1 \
--resilient \
--recover \
--max-lock 5m \
--color NEVER
)
verlog() {
if ! [[ "$verbose" = "true" ]]; then
return
fi
echo -e "$*"
}
show_help() {
echo "rclone-bisync path1 path2 [--resync] [--dry-run] [--verbose]"
echo " (--resync implies --verbose)"
}
rclone_bisync() {
rclone bisync \
"$path1" \
"$path2" \
"${bisync_args[@]}"
}
# Wonky ass function that captures stdout, stderr and the return code of provided command.
# From https://stackoverflow.com/a/59592881/3283382
# catch STDOUT_VARIABLE STDERR_VARIABLE COMMAND [ARG1[ ARG2[ ...[ ARGN]]]]
catch() {
{
IFS=$'\n' read -r -d '' "${1}";
IFS=$'\n' read -r -d '' "${2}";
(IFS=$'\n' read -r -d '' _ERRNO_; return "${_ERRNO_}");
} < <(
(
printf '\0%s\0%d\0' "$(
(
(
(
{ shift 2; "${@}"; echo "${?}" 1>&3-; } | tr -d '\0' 1>&4-
) 4>&2- 2>&1- | tr -d '\0' 1>&4-
) 3>&1- | exit "$(cat)"
) 4>&1-
)" "${?}" 1>&2
) 2>&1
)
}
run() {
verlog "Running the following command:\n" "rclone bisync $path1 $path2 ${bisync_args[*]}"
# Declare variables to use for catch
declare bisync_out bisync_err
catch bisync_out bisync_err rclone_bisync
# Save return code
bisync_errno="$?"
verlog "rclone bisync exited with $bisync_errno"
verlog "Output:\n" "$bisync_out" "$bisync_err"
# Only send message if return code is greater than 0
if (( bisync_errno > 0 )); then
summary="rclone bisync exited with $bisync_errno!"
message="Error: $bisync_err\nOutput: $bisync_out"
notify-send --urgency=critical "$summary" "$message"
fi
}
# At least two parameters must be provided.
provided_parameters="$#"
if (( provided_parameters < 2 )); then
echo "path1 and path2 must be provided!"
show_help
exit
fi
# Read paths
path1="$1"
shift
path2="$1"
shift
# Parse optional options
while :; do
case $1 in
-h|-\?|--help)
show_help
exit
;;
--resync)
bisync_args+=("--resync" "--verbose")
verbose=true
;;
--dry-run)
bisync_args+=("--dry-run")
;;
--verbose)
bisync_args+=("--verbose")
verbose=true
;;
--)
shift
break
;;
-?*)
printf 'WARN: Unknown option %s\n' "$1" >&2
exit 1
;;
*)
break
esac
shift
done
# Run!
run
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment