Skip to content

Instantly share code, notes, and snippets.

@newloong
Forked from MrTrustor/backup.sh
Created December 13, 2018 10:12
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save newloong/8ace1e6b6615cce959bff02a1885bef4 to your computer and use it in GitHub Desktop.
Save newloong/8ace1e6b6615cce959bff02a1885bef4 to your computer and use it in GitHub Desktop.
Simple backup with Duplicity and AWS Glacier
#!/bin/bash
# Copyright 2017 Théo Chamley
# Permission is hereby granted, free of charge, to any person obtaining a copy of
# this software and associated documentation files (the "Software"), to deal in the Software
# without restriction, including without limitation the rights to use, copy, modify, merge,
# publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons
# to whom the Software is furnished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in all copies or
# substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING
# BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM,
# DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
# You WILL be charged for the use of AWS Glacier. The author of this script is not in any
# way responsible for those charges.
# Simple script based on duplicity and mt-aws-glacier to backup a directory to another,
# with encryption (thanks to duplicity) and off-site backup (thanks to AWS Glacier).
# mt-aws-glacier: https://github.com/vsespb/mt-aws-glacier
# duplicy: http://duplicity.nongnu.org/
#
# Simply put it in a cron:
# 0 3 * * 1-5 bash /srv/bkp/backup.sh -s /my/dir/to/backup -d /backup/destination -m incremental
# 0 3 * * 6 bash /srv/bkp/backup.sh -s /my/dir/to/backup -d /backup/destination -m full -n 12 -g -c /path/to/mt-aws-glacier/config/glacier.cfg -v glacier-vault-name -j /path/to/glacier/log/journal-glacier-mail.log
# Duplicity passphrase for GPG encryption
export PASSPHRASE="mypassphrase"
# Lock file for not having 2 backups running at the same time
LOCK=/tmp/backup.lock
# Number of full backups to keep
NBR_OF_FULL=4
CPUS=$(lscpu | egrep "^CPU\(s\)\:" | awk '{print $NF}')
GLACIER=1
function usage() {
echo "./$0 -s <src> -d <dst> -m <mode> [-n <nbr_of_full_backups_to_keep>] [-g -c <glacier_config> -v <glacier_vault> -j <glacier_journal>] -h"
echo " * src and dst are path on the local FS"
echo " * mode is either \"full\" or \"incremental\""
echo " * nbr_of_full_backups_to_keep is 4 by default"
echo " * -g enables GLACIER upload. You need to provide"
echo " -c, -v and -j options if this is enabled."
echo " * -h : help, this message."
}
function echoerr() {
echo "$@" 1>&2;
usage
exit 1
}
function incremental() {
src=$1
dst=$2
duplicity $src file://$dst
}
function full() {
src=$1
dst=$2
nbr=$3
duplicity full $src file://$dst
duplicity remove-all-but-n-full $nbr --force file://$dst
}
function glacier() {
dst=$1
cfg=$2
vault=$3
journal=$4
mtglacier list-vaults --format mtmsg --config $cfg | grep "VaultName" | grep $vault > /dev/null
[ $? -eq 0 ] || mtglacier create-vault $vault --config $cfg
mtglacier sync --new --replace-modified --delete-removed --config $cfg --dir $dst --vault $vault --journal $journal --concurrency $CPUS
}
while getopts "s:d:m:n:gc:v:j:h" opt; do
case $opt in
s)
SRC=$OPTARG
[ -d $SRC ] || echoerr "Path $SRC does not exist."
;;
d)
DST=$OPTARG
[ -d $DST ] || mkdir -p $DST
;;
m)
MODE=$OPTARG
[ $MODE == "full" -o $MODE == "incremental" ] || echoerr "Mode is either full or incremental"
;;
n)
NBR_OF_FULL=$OPTARG
;;
g)
GLACIER=0
;;
c)
GLACIER_CONFIG=$OPTARG
;;
v)
GLACIER_VAULT=$OPTARG
;;
j)
GLACIER_JOURNAL=$OPTARG
;;
h)
usage
exit 0
;;
*)
echoerr "Unknown option $opt."
;;
esac
done
[ ! -z $SRC ] || echoerr "Missing source (-s) option."
[ ! -z $DST ] || echoerr "Missing destination (-d) option."
[ ! -z $MODE ] || echoerr "Missing mode (-m) option."
if [ $GLACIER -eq 0 ]; then
[ ! -z $GLACIER_CONFIG ] || echoerr "Glacier is enabled and missing glacier config option (-c)."
[ ! -z $GLACIER_VAULT ] || echoerr "Glacier is enabled and missing glacier vault option (-v)."
[ ! -z $GLACIER_JOURNAL ] || echoerr "Glacier is enabled and missing glacier journal option (-j)."
fi
(
flock -x -w 10 200 || exit 1
case $MODE in
"full")
full $SRC $DST $NBR_OF_FULL
;;
"incremental")
incremental $SRC $DST
;;
esac
if [ $GLACIER -eq 0 ]; then
glacier $DST $GLACIER_CONFIG $GLACIER_VAULT $GLACIER_JOURNAL
fi
) 200>$LOCK
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment