Skip to content

Instantly share code, notes, and snippets.

@pauloromeira
Last active November 13, 2023 11:33
Show Gist options
  • Save pauloromeira/c5f1dc7d3701cac2f5389a1eb609a298 to your computer and use it in GitHub Desktop.
Save pauloromeira/c5f1dc7d3701cac2f5389a1eb609a298 to your computer and use it in GitHub Desktop.
Simple backup to external device script

Simple backup to external device

This just sync any folder with an external device by using crontab. It's meant to run sparsely, hence it mounts and unmounts the device on every execution.

It consists of two scripts:

  1. with_device.sh: mounts and umounts the external device - should be in a folder with restricted access
  2. simple_backup.sh: does the actual backup using rsync - can be in any folder

Crontab sample:

# Root's crontab (sudo crontab -e)
#
# Runs every day at 4am.
#
# m h  dom mon dow   command
0 4 * * * /root/scripts/with_device.sh <DEVICE_UUID> <USER> /home/<USER>/scripts/simple_backup.sh <SOURCE_DIR> [TARGET_SUBDIR]

Notes

  • Both scripts must be marked as executable (chmod +x)
  • Because mounting requires superuser privileges, the task should be in root's crontab: sudo crontab -e
  • A log file is generated per execution with the same name as the backup script (e.g. simple_backup.log) - no appending
  • The mounting point is hidden in the same folder as the backup script with template: .tmp-mnt-<DEVICE_UUID> - this folder will be unmounted and deleted after the execution
  • Since with_device.sh runs with root privileges, you should prevent non-root users from editing it
  • Make sure your user have write permissions on the external device

Utils

  • Get device's UUID: sudo blkid /dev/sdX
#!/usr/bin/env bash
#
# example: ./with_device.sh <DEVICE_UUID> <USER> /path/to/script.sh [SCRIPT_ARGS]
# * mounting point will be added as the first script args
#
UUID="$1"
WITH_USER="$2"
SCRIPT="$3"
SCRIPT_ARGS="${@:4}"
MOUNTPOINT="$(dirname "$SCRIPT")/.tmp-mnt-$UUID"
mkdir -p "$MOUNTPOINT" && mount UUID="$UUID" "$MOUNTPOINT"
su $WITH_USER -c "$SCRIPT $MOUNTPOINT ${SCRIPT_ARGS[@]}"
umount "$MOUNTPOINT" && rm -r "$MOUNTPOINT"
#!/usr/bin/env bash
#
# example: ./simple_backup.sh <TARGET_DIR> <SOURCE_DIR> [TARGET_SUBDIR]
#
SCRIPT_FILE="$(realpath "$0")"
LOG_FILE="${SCRIPT_FILE%.sh}.log"
SOURCE="${2%/}/"
TARGET="$1/$3"
mkdir -p "$TARGET"
printf "$(date)\n\nSource: ${SOURCE}\nTarget: ${TARGET}\n\n" > "$LOG_FILE"
(time timeout 12h rsync -avh --exclude '*.tmp' --delete --progress --log-file="$LOG_FILE" "$SOURCE" "$TARGET") 2>> "$LOG_FILE"
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment