That one backup trick that stuck

Backups are boring, there is no two ways about that. It's the reason many (most?) of us fail to do them with the regularity warranted. All the more reason to make them easy and near friction less.

If your like me you don't trust a backup solution unless it's so easy to understand you could implement it by yourself in a couple of minutes. Years back, I came across this backup scheme that just used hard link copying and rsync. And that proved all I've needed since.

The hard links make sure to conserve precious disk space and not waste time on writing duplicate copies, the rsync makes sure you get all the changes accumulated since last backup applied on top of your new copy. Easy to understand, efficient and fast.

I know your supposed to keep backups offline and all that. There is best practises and there are pretty good practises. Just like pretty good privacy. Keeping things simple I just plug in my backup drive and call 'backup' wait a few seconds to a minute depending on how old that last backup were and the backup is made and the conscience is clear.

And if the worst happens, plugin your disk and copy from any of the date stamped directories in what ever way makes sense, low stress solution.

This is what I've got in my .bashrc:

function backup {
  local backup_root="/media/nthcdr/Drive"
  mountpoint -q "$backup_root" || { echo "Drive not mounted"; return 1; }

  local todays_backup="$backup_root/$(date +"%Y-%m-%d")"
  if [[ -d "$todays_backup" ]]; then
    echo "Backup already created!"
    return 0
  fi

  local partial="$backup_root/.backup-in-progress"
  local last_backup=$(find "$backup_root" -maxdepth 1 -type d -name '20*' -printf '%f\n' | sort | tail -n 1)

  rm -rf "$partial"

  if [[ -n "$last_backup" ]]; then
    echo "Hardlinking from $last_backup..."
    cp -alR "$backup_root/$last_backup/" "$partial/" || { echo "Hardlink copy failed"; return 1; }
  else
    echo "First backup, creating fresh..."
    mkdir -p "$partial"
  fi

  rsync -avX --delete \
        --exclude='.cache' \
        --exclude='.local/share/Trash' \
        --exclude='node_modules' \
        "${HOME:?HOME not set}/" "$partial/"
  local rc=$?
  if [[ $rc -eq 0 || $rc -eq 24 ]]; then
    mv "$partial" "$todays_backup"
  else
    echo "Backup failed (rsync exit $rc); partial left in $partial"
    return 1
  fi
}


Reply by email

Back

Home