Created
April 20, 2018 18:24
-
-
Save 2xsaiko/f3164c0930e38c1b37588f562b2417ae to your computer and use it in GitHub Desktop.
my backup system
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
# library | |
# sanitizes paths and interprets them as relative to / (adds / at the beginning, removes it at the end, deduplicates multiple /, removes .. and .) | |
SED_DIRSANIT='s`(^|$)`/`g;s`/+`/`g;:b;s`/\./`/`;tb;:a;s`(^|/[^/]*?)/\.\./`/`g;ta;s`^(.+)/$`\1`g' | |
# escapes strings for use in a sed command | |
SED_ESCAPE='s/[]\/$*.^[]/\\&/g' | |
die() { # vararg errmsg | |
(tput bold | |
tput setaf 1 | |
echo "$@" | |
tput sgr0)>&2 | |
exit 1 | |
} | |
warn() { # vararg msg | |
(tput bold | |
tput setaf 11 | |
echo "$@" | |
tput sgr0)>&2 | |
} | |
sed_escape() { | |
sed -e "$SED_ESCAPE" | |
} | |
is_dir_mbu() { # dir | |
test -f "$1/mbu.conf" | |
} | |
cfbd() { # dir | |
if ! is_dir_mbu "$1"; then | |
die "'$1' is not a mbu backup directory." | |
fi | |
} | |
create_bd() { # dir, srcdir | |
test -d "$2" || die "Source directory '$2' does not exist" | |
mkdir -p "$1" || die "Couldn't create backup directory '$1'." | |
touch "$1/mbu.conf" | |
setsrcdir "$1" "$2" | |
cfg_write "$1/mbu.conf" 'bdirformat' 'backup-%Y%m%d-%H%M%S' | |
touch "$1/excludes.conf" | |
} | |
setsrcdir() { # dir, srcdir | |
cfbd "$1" | |
test -d "$2" || die "Source directory '$2' does not exist" | |
cfg_write "$1/mbu.conf" 'srcdir' "$(cd "$2"; pwd)" | |
} | |
setdirformat() { # dir, dirformat | |
cfbd "$1" | |
date "+$2" > /dev/null 2> /dev/null || die "Invalid format. Look at \`man date\` for more info." | |
printf 'Preview: %s\n' "$(date "+$2")" | |
cfg_write "$1/mbu.conf" 'bdirformat' "$2" | |
} | |
get_new_backup_dir() { # dir | |
cfbd "$1" | |
cfg_haskey "$1/mbu.conf" 'bdirformat' || cfg_write "$1/mbu.conf" 'bdirformat' 'backup-%Y%m%d-%H%M%S' | |
local format="$(cfg_read "$1/mbu.conf" 'bdirformat')" | |
date "+$format" | |
} | |
execbackup() { # dir | |
cfbd "$1" | |
local backupdir="$(get_new_backup_dir "$1")" | |
local bdpath="$1/$backupdir" | |
printf "Creating backup '%s'\n" "$backupdir" | |
mkdir -p "$bdpath/files" || die "Could not create backup directory." | |
touch "$bdpath/backup.conf" | |
local prevb_args="" | |
if cfg_haskey "$1/mbu.conf" 'latest'; then | |
local prevbackup="$(cfg_read "$1/mbu.conf" 'latest')" | |
if [ -d "$1/$prevbackup/files" ]; then | |
cfg_write "$bdpath/backup.conf" 'prev' "$prevbackup" | |
prevb_args="--link-dest=../../$prevbackup/files " | |
else | |
warn "Nonexistent previous backup: '$prevbackup'" | |
fi | |
fi | |
local sourcedir="$(cfg_read "$1/mbu.conf" 'srcdir')/" | |
test -d "$sourcedir" || die "Source directory '$sourcedir' does not exist." | |
local excludesfile="$1/excludes.conf" | |
# local excludesfile="/tmp/excludes_$RANDOM.tmp" | |
# do the thing | |
rsync -aAXSh --info=progress2 --delete --exclude-from="$excludesfile" ${prevb_args} "$sourcedir" "$bdpath/files/" || die "Error while backing up files." | |
# rm "$excludesfile" | |
cfg_write "$1/mbu.conf" 'latest' "$backupdir" | |
echo 'Backup finished!' | |
} | |
exclude_add() { # dir, excludedir | |
cfbd "$1" | |
test "x$2" = "x" && die "Empty exclude directory" | |
echo "$2" >> "$1/excludes.conf" | |
exclude_cleanup "$1" | |
} | |
exclude_remove() { # dir, excludedir | |
cfbd "$1" | |
sed -i "/^$(echo $2 | sed_escape)$/d" "$1/excludes.conf" | |
exclude_cleanup "$1" | |
} | |
exclude_list() { # dir | |
cfbd "$1" | |
cat "$1/excludes.conf" | sed "s|^|($(cfg_read "$1/mbu.conf" srcdir))|g" | |
} | |
exclude_cleanup() { # dir | |
cfbd "$1" | |
local tmpfile=/tmp/.excludes.$RANDOM.conf | |
cp "$1/excludes.conf" "$tmpfile" | |
sed -Ei "$SED_DIRSANIT" "$tmpfile" | |
sort -uo "$tmpfile" "$tmpfile" | |
mv "$tmpfile" "$1/excludes.conf" | |
} | |
purge() { # dir, keep_no | |
cfbd "$1" | |
die stub | |
} | |
getprev() { # path, backup_instance | |
cfbd "$1" | |
test -f "$1/$2/backup.conf" || die "'$2' is not a valid backup" | |
cfg_haskey "$1/$2/backup.conf" 'prev' && cfg_read "$1/$2/backup.conf" 'prev' | |
} | |
cfg_write() { # path, key, value | |
cfg_delete "$1" "$2" | |
echo "$2=$3" >> "$1" | |
} | |
cfg_read() { # path, key -> value | |
test -f "$1" && grep "^$(echo "$2" | sed_escape)=" "$1" | sed "s/^$(echo "$2" | sed_escape)=//" | tail -1 | |
} | |
cfg_delete() { # path, key | |
test -f "$1" && sed -i "/^$(echo $2 | sed_escape).*$/d" "$1" | |
} | |
cfg_haskey() { # path, key | |
test -f "$1" && grep "^$(echo "$2" | sed_escape)=" "$1" > /dev/null | |
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
source $(dirname "$(readlink -f "$0")")/lib/libmbu.sh || exit 5 | |
print_help() { | |
cat <<EOF | |
usage: mbu <backup dir> <operation> [...] | |
operations: | |
mbu <backup dir> create <source dir> | |
mbu <backup dir> backup | |
mbu <backup dir> excla <subdir> | |
mbu <backup dir> exclr <subdir> | |
mbu <backup dir> excll | |
mbu <backup dir> setbf <format> | |
mbu <backup dir> setsrc <source dir> | |
mbu <backup dir> purge | |
create: Creates a new backup directory. | |
backup: Creates a new incremental backup. | |
excla: Adds a new excluded file/directory. | |
exclr: Removes a file/directory from the excludes list. | |
excll: Lists the currently excluded files/directories. | |
setbf: Sets the format for the backup folders. | |
See \`man date\` for more information about the format. | |
setsrc: Changes the source directory. | |
purge: Purges everything but the last 4 backups. | |
EOF | |
exit 2 | |
} | |
case "$2" in | |
create) | |
create_bd "$1" "$3" | |
;; | |
backup) | |
execbackup "$1" | |
;; | |
excla) | |
exclude_add "$1" "$3" | |
;; | |
exclr) | |
exclude_remove "$1" "$3" | |
;; | |
excll) | |
exclude_list "$1" | |
;; | |
setbf) | |
setdirformat "$1" "$3" | |
;; | |
setsrc) | |
setsrcdir "$1" "$3" | |
;; | |
purge) | |
purge "$1" 4 | |
;; | |
*) | |
print_help | |
;; | |
esac |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment