This script will perform a full system backup with rsync, leaving out /dev and /tmp and what not.
There are several configuration parameters:
target
: system to back up, must be set to output of uname -n
. Used as a sanity check.
source_dir
: source directory. Set to /
for full system backup.
target_dir
: target directory. Set to the mountpoint of an external hard drive or a remote server. Note: make sure that target_dir
or a parent is included in exclude_dir
otherwise rsync will recurse and your hard drive will get filled up completely.
exclude_dir
: excluded directories. Set these to temporary directories and other things you don't want backed up.
include_dir
: included directories. Subfolders of excluded directories to include.
If you want to use this script with a remote host where the target user is not root, change flags to
flags=(-avPse ssh --delete --ignore-errors --rsync-path="rsync --fake-super")
and use a remote path of the form user@host:path
for target_dir
#!/bin/bash set -f hostname=$(hostname -s) target="my-hostname" source_dir="/" target_dir="/media/external-hard-drive/$target/" exclude_dir=(*/.gvfs /media /run/media /sys /dev /proc /mnt /tmp pagefile.sys hiberfil.sys /home/*/.cache .mozilla/firefox/*/Cache .Trash-1000) include_dir=(/mnt/linux-data/opt /mnt/data) flags=(-avPAX --delete --ignore-errors) if [ -n "$target" ] ; then if [ "$hostname" != "$target" ] ; then echo Error: must be run on $target exit 1 fi fi include=() # process include directories for d in "${include_dir[@]}" do found=0 dir="" shortest_parent="/" echo include_dir $d # Need to deal with rsync idiosyncracies # by including excluded directories # but not their contents # Removes matches to the include directory # and finds the shortest parent path for d2 in "${exclude_dir[@]}" do echo exclude_dir $d2 if [[ $d = $d2* ]]; then found=1 if [[ "$shortest_parent" == "/" ]]; then shortest_parent=$d2 else if [ ${#shortest_parent} -gt ${#d2} ]; then shortest_parent=$d2 fi fi fi echo shortest_parent $shortest_parent done if [[ $found ]]; then path=$(dirname "$d") while [[ "$path" != "/" ]]; do exclude_dir+=("$path/*") include+=("--include=$path") if [[ "$path" == "$shortest_parent" ]]; then break fi path=$(dirname "$path") done fi include+=("--include=$d") done exclude=() for d in "${exclude_dir[@]}" do exclude+=("--exclude=$d") done sudo -E rsync "${flags[@]}" "${include[@]}" "${exclude[@]}" "$source_dir" "$target_dir"