Compare commits
46 commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
c78676ab9d | ||
|
|
2dec3ed145 | ||
|
|
c56e78a463 | ||
|
|
27785d0ad0 | ||
|
|
4dd6ed1ee2 | ||
|
|
5cad03cb3e | ||
|
|
f71dd556dc | ||
|
|
77ecc4318f | ||
|
|
99b2512789 | ||
|
|
4779ee4d1b | ||
|
|
96a64148fd | ||
|
|
6140c226db | ||
|
|
18ef8983aa | ||
|
|
734be37b6d | ||
|
|
9fea5075ab | ||
|
|
ae37de0e65 | ||
|
|
2a77dde6ee | ||
|
|
e070ca7887 | ||
|
|
5a023c3609 | ||
|
|
6377ad5281 | ||
|
|
649c7830b0 | ||
|
|
dba25a57de | ||
|
|
13af8206e3 | ||
|
|
9a36453bb1 | ||
|
|
a7752c4c78 | ||
|
|
06291f0a6e | ||
|
|
cd82c07579 | ||
|
|
de7a6be9fe | ||
|
|
98bcf9f673 | ||
|
|
0c4f2b7c45 | ||
|
|
2389ee61db | ||
|
|
def00abe60 | ||
|
|
e4df413036 | ||
|
|
dd2189ec4d | ||
|
|
f8c4d0cc16 | ||
|
|
723945af44 | ||
|
|
b7c292b5ff | ||
|
|
cc2ae25355 | ||
|
|
d1311a185a | ||
|
|
25d63bb99f | ||
|
|
2ad58dc07e | ||
|
|
418ab79b11 | ||
|
|
6ba17fa268 | ||
|
|
b207b90cba | ||
|
|
fb54103607 | ||
|
|
d2ae7c58c1 |
6 changed files with 255 additions and 73 deletions
|
|
@ -3,12 +3,8 @@ language: bash
|
|||
# Use container-based infrastructure for quicker build start-up
|
||||
sudo: false
|
||||
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- debian-sid
|
||||
packages:
|
||||
- shellcheck
|
||||
before_script:
|
||||
- shellcheck --version
|
||||
|
||||
script:
|
||||
- shellcheck -e SC2034 duplicity-backup.sh duplicity-backup.conf.example
|
||||
|
|
|
|||
38
CHANGELOG
38
CHANGELOG
|
|
@ -1,6 +1,38 @@
|
|||
vX.X (XXXX-XX-XX)
|
||||
=================
|
||||
* placeholder for next version's changelog
|
||||
vX.X.X (unreleased)
|
||||
===================
|
||||
|
||||
v1.6.0 (2018-05-22)
|
||||
===================
|
||||
* Add support for Dropbox backend (by xmatthias)
|
||||
* Fix issue #177: bug in `--cleanup` action (thanks smcgrat)
|
||||
|
||||
v1.5.0 (2018-01-15)
|
||||
===================
|
||||
* Add support for B2 backend (by harrim4n)
|
||||
|
||||
v1.4.3 (2017-10-30)
|
||||
===================
|
||||
* Add support for Telegram notifications (by GerardRibas)
|
||||
|
||||
v1.4.2 (2017-10-30)
|
||||
===================
|
||||
* Remove VERSION file and hardcode it directly in the script. Fix issue #164 (thanks regelga)
|
||||
|
||||
v1.4.1 (2017-10-04)
|
||||
===================
|
||||
* Show program versions in output.
|
||||
|
||||
v1.4.0 (2017-09-24)
|
||||
===================
|
||||
* Add version check of duplicity to handle deprecation of --include-globbing-filelist
|
||||
* Bugfixes
|
||||
|
||||
v1.3.0 (2016-10-23)
|
||||
===================
|
||||
* Fix GPG error when backing up the script if no specific keyring is set up.
|
||||
* Attempt to fix issue #145 by adding a `GPG_OPTIONS` parameter.
|
||||
* Add `-h` / `--help` option to print usage and don't send email or notification when printing usage only
|
||||
* Rename repository from 'duplicity-backup' to 'duplicity-backup.sh'.
|
||||
|
||||
v1.2 (2016-09-10)
|
||||
=================
|
||||
|
|
|
|||
43
README.md
43
README.md
|
|
@ -1,4 +1,4 @@
|
|||
[](https://travis-ci.org/zertrin/duplicity-backup)
|
||||
[](https://travis-ci.org/zertrin/duplicity-backup.sh)
|
||||
|
||||
# duplicity-backup.sh
|
||||
|
||||
|
|
@ -31,7 +31,7 @@ This means the following:
|
|||
|
||||
## Contributing
|
||||
|
||||
The development version of the code is available at https://github.com/zertrin/duplicity-backup in the `dev` branch. It is a bleeding-edge version with the latests changes that have not yet been tested a lot, but that's the best starting point to contribute.
|
||||
The development version of the code is available at https://github.com/zertrin/duplicity-backup.sh in the `dev` branch. It is a bleeding-edge version with the latest changes that have not yet been tested a lot, but that's the best starting point to contribute.
|
||||
|
||||
Pull requests are welcome! However please **always use individual feature branches for each pull request**. I may not accept a pull request from a master or dev branch.
|
||||
|
||||
|
|
@ -39,12 +39,12 @@ Here is how to do it:
|
|||
|
||||
Fork the repository first and then clone your fork on your machine:
|
||||
|
||||
git clone git@github.com:YOURNAME/duplicity-backup.git
|
||||
git clone git@github.com:YOURNAME/duplicity-backup.sh.git duplicity-backup
|
||||
cd duplicity-backup
|
||||
|
||||
Add a remote for the upstream repository:
|
||||
|
||||
git remote add upstream git@github.com:zertrin/duplicity-backup.git
|
||||
git remote add upstream git@github.com:zertrin/duplicity-backup.sh.git
|
||||
git fetch upstream
|
||||
|
||||
Create a new topic branch for the changes you want to make, based on the `dev` branch from upstream:
|
||||
|
|
@ -57,7 +57,7 @@ Make your changes, test them, commit them and push them to Github:
|
|||
|
||||
Open a Pull request from `YOURNAME:my-fix-1` to `zertrin:dev`.
|
||||
|
||||
If you want to open another pull request for another change which is independant of the previous one, just create another topic branch based on master (`git checkout -b my-fix-2 upstream/dev`)
|
||||
If you want to open another pull request for another change which is independent of the previous one, just create another topic branch based on master (`git checkout -b my-fix-2 upstream/dev`)
|
||||
|
||||
|
||||
## Installation
|
||||
|
|
@ -66,22 +66,25 @@ If you want to open another pull request for another change which is independant
|
|||
|
||||
You can clone the repository (which makes it easy to get future updates):
|
||||
|
||||
git clone https://github.com/zertrin/duplicity-backup.git duplicity-backup
|
||||
git clone https://github.com/zertrin/duplicity-backup.sh.git duplicity-backup
|
||||
|
||||
If you prefer the stable version do:
|
||||
If you prefer the stable (but old) version do:
|
||||
|
||||
git checkout stable
|
||||
|
||||
... or if you want the latest version (might still have bugs), then:
|
||||
... or if you want the normal version, then:
|
||||
|
||||
git checkout master
|
||||
|
||||
... or if you like living on the edge, you can stay at the development version which is automatically cloned.
|
||||
... or if you like living on the edge (or need the latest bugfixes), you can stay at the development version which is automatically cloned.
|
||||
|
||||
Or just download the ZIP file:
|
||||
|
||||
* For the stable branch: https://github.com/zertrin/duplicity-backup/archive/stable.zip
|
||||
* For the normal branch: https://github.com/zertrin/duplicity-backup/archive/master.zip
|
||||
| Version | Download link |
|
||||
|---------------|-------------------------------------------------------------------|
|
||||
| stable (old) | https://github.com/zertrin/duplicity-backup.sh/archive/stable.zip |
|
||||
| normal | https://github.com/zertrin/duplicity-backup.sh/archive/master.zip |
|
||||
| latest | https://github.com/zertrin/duplicity-backup.sh/archive/dev.zip |
|
||||
|
||||
### 2. Configure the script
|
||||
|
||||
|
|
@ -94,7 +97,7 @@ The script looks for its configuration by reading the path to the config file sp
|
|||
If no config file was given on the command line, the script will try to find the file specified in the `CONFIG` parameter at the beginning of the script (default: `duplicity-backup.conf` in the script's directory).
|
||||
|
||||
So be sure to either:
|
||||
* specify the configuration file path on the command line with the -c option **[recommended]**
|
||||
* specify the configuration file path on the command line with the `-c` option **[recommended]**
|
||||
* or to edit the `CONFIG` parameter in the script to match the actual location of your config file. **[deprecated]** _(will be removed in future versions of the script)_
|
||||
|
||||
NOTE: to ease future updates of the script, you may prefer NOT to edit the script at all and to specify systematically the path to your config file on the command line with the `-c` or `--config` option.
|
||||
|
|
@ -120,13 +123,13 @@ else just download again the ZIP archive an extract it over the existing folder.
|
|||
|
||||
Then compare the example config file (`duplicity-backup.conf.example`) with your modified version (for example `/etc/duplicity-backup.conf`) and adapt your copy to reflect the changes in the example file.
|
||||
|
||||
Thare are many ways to do so, here are some examples (adapt the path to your actual files):
|
||||
There are many ways to do so, here are some examples (adapt the path to your actual files):
|
||||
|
||||
diff duplicity-backup.conf.example /etc/duplicity-backup.conf
|
||||
vimdiff duplicity-backup.conf.example /etc/duplicity-backup.conf
|
||||
|
||||
|
||||
## Dependancies
|
||||
## Dependencies
|
||||
|
||||
* [duplicity](http://duplicity.nongnu.org/)
|
||||
* Basic utilities like: [bash](https://www.gnu.org/software/bash/), [which](http://unixhelp.ed.ac.uk/CGI/man-cgi?which), [find](https://www.gnu.org/software/findutils/) and [tee](http://linux.die.net/man/1/tee) (should already be available on most Linux systems)
|
||||
|
|
@ -136,6 +139,9 @@ Thare are many ways to do so, here are some examples (adapt the path to your act
|
|||
For the [Amazon S3](https://aws.amazon.com/s3/) storage backend *`optional`*
|
||||
* [s3cmd](http://s3tools.org/s3cmd) *`optional`*
|
||||
|
||||
For the [Backblaze B2](https://www.backblaze.com/b2) storage backend *`optional`*
|
||||
* [python-b2](https://pypi.python.org/pypi/b2) *`optional`*
|
||||
|
||||
For the [Google Cloud Storage](https://cloud.google.com/storage/) storage backend *`optional`*
|
||||
* [boto](https://github.com/boto/boto) (may already have been installed with duplicity)
|
||||
* [gsutil](https://cloud.google.com/storage/docs/gsutil) *`optional`*
|
||||
|
|
@ -246,14 +252,19 @@ Note that the commands `--restore-file` and `--restore-dir` are equivalent.
|
|||
|
||||
## Known issues
|
||||
|
||||
### GPG error if system locale is not english
|
||||
|
||||
If your system's locale is not english, an error can happen when duplicity is trying to encrypt the files with gpg. This problem concerns duplicity and has been reported upstream ([see bug report](https://bugs.launchpad.net/duplicity/+bug/510625)). A simple workaround is to set the following environement variable: `LANG=C`. For example: `LANG=C duplicity-backup.sh [-c config_file] ...` or in the cron `41 3 * * * LANG=C /absolute/path/to/duplicity-backup.sh -c /etc/duplicity-backup.conf -b`
|
||||
|
||||
### "/dev/fd/62: Operation not supported" errors on FreeBSD
|
||||
|
||||
See [issue #143](https://github.com/zertrin/duplicity-backup.sh/issues/143) for a fix.
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
This script attempts to simplify the task of running a duplicity command; if you are having any problems with the script the first step is to determine if the script is generating an incorrect command or if duplicity itself is causing your error.
|
||||
|
||||
To see exactly what is happening when you run duplicity-backup, either pass the option `-d` or `--debug` on the command line, or head to the bottom of the configuration file and uncomment the `ECHO=$(which echo)` variable.
|
||||
To see exactly what is happening when you run duplicity-backup.sh, either pass the option `-d` or `--debug` on the command line, or head to the bottom of the configuration file and uncomment the `ECHO=$(which echo)` variable.
|
||||
|
||||
This will stop the script from running and will, instead, output the generated command into your log file. You can then check to see if what is being generated is causing an error or if it is duplicity causing you woe.
|
||||
|
||||
|
|
@ -266,5 +277,5 @@ You can also try the `-n` or `--dry-run` option. This will make duplicity to cal
|
|||
* Show backup-ed files in today incremental backup email
|
||||
|
||||
|
||||
###### Thanks to all the [contributors](https://github.com/zertrin/duplicity-backup/graphs/contributors) for their help.
|
||||
###### Thanks to all the [contributors](https://github.com/zertrin/duplicity-backup.sh/graphs/contributors) for their help.
|
||||
|
||||
|
|
|
|||
1
VERSION
1
VERSION
|
|
@ -1 +0,0 @@
|
|||
v1.2
|
||||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Copyright (c) 2008-2010 Damon Timm.
|
||||
# Copyright (c) 2010 Mario Santagiuliana.
|
||||
# Copyright (c) 2012-2015 Marc Gallet.
|
||||
# Copyright (c) 2012-2018 Marc Gallet.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -23,10 +23,10 @@
|
|||
# http://damontimm.com/code/dt-s3-backup (for the original program by Damon Timm)
|
||||
#
|
||||
# Latest code available at:
|
||||
# http://github.com/zertrin/duplicity-backup
|
||||
# http://github.com/zertrin/duplicity-backup.sh
|
||||
#
|
||||
# List of contributors:
|
||||
# https://github.com/zertrin/duplicity-backup/graphs/contributors
|
||||
# https://github.com/zertrin/duplicity-backup.sh/graphs/contributors
|
||||
#
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
|
|
@ -75,7 +75,7 @@
|
|||
# This can be / or somewhere else -- I use /home/ because all the
|
||||
# directories that I want to backup start with /home/.
|
||||
#
|
||||
ROOT="/home"
|
||||
ROOT='/home'
|
||||
|
||||
# Set hostname for this duplicity instance, useful for e-mail reports
|
||||
#
|
||||
|
|
@ -108,13 +108,14 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
|
|||
#DEST="ftpes://user[:password]@other.host[:port]/some_dir"
|
||||
#DEST="rsync://user@host.com[:port]//absolute_path"
|
||||
#DEST="scp://user[:password]@other.host[:port]/[/]some_dir"
|
||||
#DEST="ssh://user[:password]@other.host[:port]/[/]some_dir"
|
||||
#DEST="sftp://user[:password]@other.host[:port]/[/]some_dir"
|
||||
#DEST="file:///home/foobar_user_name/new-backup-test/"
|
||||
#DEST="imap[s]://user[:password]@host.com[/from_address_prefix]"
|
||||
#DEST="webdav[s]://user[:password]@other.host[:port]/some_dir"
|
||||
#DEST="gdocs://foobar_google_account/some_dir"
|
||||
#DEST="swift://foobar_swift_container/some_dir"
|
||||
#DEST="dpbx:///foobar_swift_container/some_dir"
|
||||
#DEST="b2://some_account_id[:some_application_key]@some_bucket_name/some_dir"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
@ -128,7 +129,7 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
|
|||
# setting it in the backend url (which might be readable in the operating
|
||||
# systems process listing to other users on the same machine)."
|
||||
#
|
||||
#FTP_PASSWORD="password"
|
||||
#FTP_PASSWORD='password'
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
@ -173,6 +174,13 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
|
|||
#SWIFT_AUTHURL="foobar_swift_authurl"
|
||||
#SWIFT_AUTHVERSION="2"
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# DROPBOX INFORMATION
|
||||
# ------------------------------------------------------------------------------
|
||||
# Uncomment these lines if you're using Dropbox
|
||||
#
|
||||
#DPBX_ACCESS_TOKEN="foobar_dropbox_access_token"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# INCLUDE LIST OF DIRECTORIES
|
||||
|
|
@ -182,15 +190,15 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
|
|||
#
|
||||
# Here is an example with multiple locations:
|
||||
#
|
||||
#INCLIST=( "/home/*/Documents" \
|
||||
# "/home/*/Projects" \
|
||||
# "/home/*/logs" \
|
||||
# "/home/www/mysql-backups" \
|
||||
#INCLIST=( '/home/*/Documents' \
|
||||
# '/home/*/Projects' \
|
||||
# '/home/*/logs' \
|
||||
# '/home/www/mysql-backups' \
|
||||
# )
|
||||
#
|
||||
# Simpler example with one location:
|
||||
|
||||
INCLIST=( "/home/foobar_user_name/Documents/" )
|
||||
INCLIST=( '/home/foobar_user_name/Documents/' )
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
@ -202,18 +210,18 @@ INCLIST=( "/home/foobar_user_name/Documents/" )
|
|||
#
|
||||
# Here is an example with multiple locations:
|
||||
#
|
||||
#EXCLIST=( "/home/*/Trash" \
|
||||
# "/home/*/Projects/Completed" \
|
||||
# "/**.DS_Store" \
|
||||
# "/**Icon?" \
|
||||
# "/**.AppleDouble" \
|
||||
#EXCLIST=( '/home/*/Trash' \
|
||||
# '/home/*/Projects/Completed' \
|
||||
# '/**.DS_Store' \
|
||||
# '/**Icon?' \
|
||||
# '/**.AppleDouble' \
|
||||
# )
|
||||
#
|
||||
# If you don't want to exclude anything, use EXCLIST=()
|
||||
#
|
||||
# Simpler example with one location. Adapt it to your needs.
|
||||
|
||||
EXCLIST=( "/home/foobar_user_name/Documents/foobar-to-exclude" )
|
||||
EXCLIST=( '/home/foobar_user_name/Documents/foobar-to-exclude' )
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
@ -260,9 +268,9 @@ ENCRYPTION='yes'
|
|||
# (your backups will be encrypted with this password) or is used
|
||||
# for the "GPG_SIGN_KEY" (see below).
|
||||
# Comment out if you aren't using encryption
|
||||
# Note: if you have a '$' in your passphrase, escape it with a '\'
|
||||
# Note: if you have a ' in your passphrase, escape it accordingly.
|
||||
|
||||
PASSPHRASE="foobar_gpg_passphrase"
|
||||
PASSPHRASE='foobar_gpg_passphrase'
|
||||
|
||||
# Specify which GPG keys you would like to use (even if you have only one).
|
||||
# If you are running this from a cron, it is highly recommended to create separate
|
||||
|
|
@ -292,6 +300,14 @@ GPG_SIGN_KEY="foobar_gpg_key"
|
|||
#
|
||||
#SECRET_KEYRING="/home/foobar_user_name/.gnupg/duplicity.gpg
|
||||
|
||||
# Here you can specify options that will be passed to GPG.
|
||||
# If you can, avoid using quotes here, as it hasn't been tested much yet.
|
||||
# You shouldn't need to remove the following default (--no-show-photos)
|
||||
# For example an user reported (GitHub issue #145) that since gnupg v2.1,
|
||||
# the option "--pinentry-mode loopback" is necessary,
|
||||
# then set GPG_OPTIONS="--no-show-photos --pinentry-mode loopback"
|
||||
GPG_OPTIONS="--no-show-photos"
|
||||
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# STATIC BACKUP OPTIONS
|
||||
|
|
@ -411,7 +427,7 @@ MAIL="mailx" # default command for Linux mail
|
|||
# Third-party notification services. If NOTIFICATION_SERVICE is not provided, no
|
||||
# notifications will be sent.
|
||||
|
||||
# Possible values for NOTIFICATION_SERVICE are: slack, pushover, ifttt
|
||||
# Possible values for NOTIFICATION_SERVICE are: slack, pushover, ifttt, telegram
|
||||
NOTIFICATION_SERVICE=""
|
||||
NOTIFICATION_FAILURE_ONLY="yes" # send notifications only if there was an error while creating backup
|
||||
|
||||
|
|
@ -431,6 +447,10 @@ IFTTT_MAKER_EVENT="duplicity" # name the event to trigger at IFTTT Maker Channel
|
|||
IFTTT_HOOK_URL="https://maker.ifttt.com/trigger/$IFTTT_MAKER_EVENT/with/key/$IFTTT_KEY" # ONLY change this if IFTTT changes it
|
||||
IFTTT_VALUE2="" # general purpose value to pass to your maker channel (optional)
|
||||
|
||||
# Provider: Telegram
|
||||
TELEGRAM_CHATID="" #Generate a Telegram bot following guide: https://core.telegram.org/bots#3-how-do-i-create-a-bot
|
||||
TELEGRAM_KEY=""
|
||||
|
||||
# ------------------------------------------------------------------------------
|
||||
# TROUBLESHOOTING
|
||||
# ------------------------------------------------------------------------------
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@
|
|||
#
|
||||
# Copyright (c) 2008-2010 Damon Timm.
|
||||
# Copyright (c) 2010 Mario Santagiuliana.
|
||||
# Copyright (c) 2012 Marc Gallet.
|
||||
# Copyright (c) 2012-2018 Marc Gallet.
|
||||
#
|
||||
# This program is free software: you can redistribute it and/or modify it under
|
||||
# the terms of the GNU General Public License as published by the Free Software
|
||||
|
|
@ -23,7 +23,10 @@
|
|||
# http://damontimm.com/code/dt-s3-backup (for the original program by Damon Timm)
|
||||
#
|
||||
# Latest code available at:
|
||||
# http://github.com/zertrin/duplicity-backup
|
||||
# http://github.com/zertrin/duplicity-backup.sh
|
||||
#
|
||||
# List of contributors:
|
||||
# https://github.com/zertrin/duplicity-backup.sh/graphs/contributors
|
||||
#
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
|
|
@ -42,6 +45,8 @@ CONFIG="duplicity-backup.conf"
|
|||
# Script Happens Below This Line - Shouldn't Require Editing #
|
||||
##############################################################
|
||||
|
||||
DBSH_VERSION="v1.6.0"
|
||||
|
||||
# make a backup of stdout and stderr for later
|
||||
exec 6>&1
|
||||
exec 7>&2
|
||||
|
|
@ -78,12 +83,13 @@ echo "USAGE:
|
|||
the current working directory
|
||||
|
||||
-q, --quiet silence most of output messages, except errors and output
|
||||
that is intended for interactive usage. Silenced output
|
||||
that are intended for interactive usage. Silenced output
|
||||
is still logged in the logfile.
|
||||
|
||||
-n, --dry-run perform a trial run with no changes made
|
||||
-d, --debug echo duplicity commands to logfile
|
||||
-V, --version print version information about this script and duplicity
|
||||
-h, --help print this help and exit
|
||||
|
||||
CURRENT SCRIPT VARIABLES:
|
||||
========================
|
||||
|
|
@ -93,6 +99,7 @@ echo "USAGE:
|
|||
ROOT (root directory of backup) = ${ROOT}
|
||||
LOGFILE (log file path) = ${LOGFILE}
|
||||
" >&6
|
||||
USAGE=1
|
||||
}
|
||||
|
||||
DUPLICITY="$(which duplicity)"
|
||||
|
|
@ -102,19 +109,39 @@ if [ ! -x "${DUPLICITY}" ]; then
|
|||
exit 1
|
||||
fi
|
||||
|
||||
version(){
|
||||
# Read the version string from the file VERSION
|
||||
VERSION=$(<VERSION)
|
||||
DUPLICITY_VERSION=$(${DUPLICITY} --version)
|
||||
DUPLICITY_VERSION=${DUPLICITY_VERSION//[^0-9\.]/}
|
||||
|
||||
echo "duplicity-backup.sh ${VERSION}"
|
||||
${DUPLICITY} --version
|
||||
version_compare() {
|
||||
if [[ $1 =~ ^([0-9]+\.?)+$ && $2 =~ ^([0-9]+\.?)+$ ]]; then
|
||||
local l=(${1//./ }) r=(${2//./ }) s=${#l[@]}; [[ ${#r[@]} -gt ${#l[@]} ]] && s=${#r[@]}
|
||||
|
||||
for i in $(seq 0 $((s - 1))); do
|
||||
[[ ${l[$i]} -gt ${r[$i]} ]] && return 1
|
||||
[[ ${l[$i]} -lt ${r[$i]} ]] && return 2
|
||||
done
|
||||
|
||||
return 0
|
||||
else
|
||||
echo "Invalid version number given"
|
||||
exit 1
|
||||
fi
|
||||
}
|
||||
|
||||
# set a flag if duplicity's version is lower than 0.7, for usage later in the script
|
||||
version_compare "${DUPLICITY_VERSION}" 0.7
|
||||
case $? in 2) LT07=1;; *) LT07=0;; esac
|
||||
|
||||
version(){
|
||||
echo "duplicity-backup.sh ${DBSH_VERSION}"
|
||||
echo "duplicity ${DUPLICITY_VERSION}"
|
||||
exit 0
|
||||
}
|
||||
|
||||
# Some expensive argument parsing that allows the script to
|
||||
# be insensitive to the order of appearance of the options
|
||||
# and to handle correctly option parameters that are optional
|
||||
while getopts ":c:t:bfvelsqndV-:" opt; do
|
||||
while getopts ":c:t:bfvelsqndhV-:" opt; do
|
||||
case $opt in
|
||||
# parse long options (a bit tricky because builtin getopts does not
|
||||
# manage long options and I don't want to impose GNU getopt dependancy)
|
||||
|
|
@ -164,11 +191,15 @@ while getopts ":c:t:bfvelsqndV-:" opt; do
|
|||
QUIET=1
|
||||
;;
|
||||
dry-run)
|
||||
DRY_RUN="--dry-run "
|
||||
DRY_RUN="--dry-run"
|
||||
;;
|
||||
debug)
|
||||
ECHO=$(which echo)
|
||||
;;
|
||||
help)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
version)
|
||||
version
|
||||
;;
|
||||
|
|
@ -187,8 +218,12 @@ while getopts ":c:t:bfvelsqndV-:" opt; do
|
|||
l) COMMAND="list-current-files";;
|
||||
s) COMMAND="collection-status";;
|
||||
q) QUIET=1;;
|
||||
n) DRY_RUN="--dry-run ";; # dry run
|
||||
n) DRY_RUN="--dry-run";; # dry run
|
||||
d) ECHO=$(which echo);; # debug
|
||||
h)
|
||||
usage
|
||||
exit 0
|
||||
;;
|
||||
V) version;;
|
||||
:)
|
||||
echo "Option -${OPTARG} requires an argument." >&2
|
||||
|
|
@ -270,7 +305,7 @@ fi
|
|||
# fd1 is stdout and is always logged but only shown if not QUIET
|
||||
# fd2 is stderr and is always shown on screen and logged
|
||||
# fd3 is like stdout but always shown on screen (for interactive prompts)
|
||||
# fd4 is always shown on sceen but never logged (for the usage text)
|
||||
# fd4 is always shown on screen but never logged (for the usage text)
|
||||
# fd5 is never shown on screen but always logged (for delimiters in the log)
|
||||
#
|
||||
|
||||
|
|
@ -307,7 +342,13 @@ fi
|
|||
|
||||
# ------------------------- Setting up variables ------------------------
|
||||
|
||||
STATIC_OPTIONS="${DRY_RUN}${STATIC_OPTIONS}"
|
||||
if [ -n "${DRY_RUN}" ]; then
|
||||
STATIC_OPTIONS="${DRY_RUN} ${STATIC_OPTIONS}"
|
||||
fi
|
||||
|
||||
if [ -n "${STORAGECLASS}" ]; then
|
||||
STATIC_OPTIONS="${STATIC_OPTIONS} ${STORAGECLASS}"
|
||||
fi
|
||||
|
||||
SIGN_PASSPHRASE=${PASSPHRASE}
|
||||
|
||||
|
|
@ -319,6 +360,7 @@ export SWIFT_USERNAME
|
|||
export SWIFT_PASSWORD
|
||||
export SWIFT_AUTHURL
|
||||
export SWIFT_AUTHVERSION
|
||||
export DPBX_ACCESS_TOKEN
|
||||
export PASSPHRASE
|
||||
export SIGN_PASSPHRASE
|
||||
|
||||
|
|
@ -335,7 +377,7 @@ fi
|
|||
LOCKFILE=${LOGDIR}backup.lock
|
||||
|
||||
if [ "${ENCRYPTION}" = "yes" ]; then
|
||||
ENCRYPT="--gpg-options \"--no-show-photos\""
|
||||
ENCRYPT="--gpg-options \"${GPG_OPTIONS}\""
|
||||
if [ ! -z "${GPG_ENC_KEY}" ] && [ ! -z "${GPG_SIGN_KEY}" ]; then
|
||||
if [ "${HIDE_KEY_ID}" = "yes" ]; then
|
||||
ENCRYPT="${ENCRYPT} --hidden-encrypt-key=${GPG_ENC_KEY}"
|
||||
|
|
@ -368,6 +410,9 @@ NO_S3CMD_CFG="WARNING: s3cmd is not configured, run 's3cmd --configure' \
|
|||
in order to retrieve remote file size information. Remote file \
|
||||
size information unavailable."
|
||||
|
||||
NO_B2CMD="WARNING: b2 not found in PATH, remote file size information \
|
||||
unavailable. Is the python-b2 package installed?"
|
||||
|
||||
README_TXT="In case you've long forgotten, this is a backup script that you used to backup some files (most likely remotely at Amazon S3). In order to restore these files, you first need to import your GPG private(s) key(s) (if you haven't already). The key(s) is/are in this directory and the following command(s) should do the trick:\n\nIf you were using the same key for encryption and signature:\n gpg --allow-secret-key-import --import duplicity-backup-encryption-and-sign-secret.key.txt\nOr if you were using two separate keys for encryption and signature:\n gpg --allow-secret-key-import --import duplicity-backup-encryption-secret.key.txt\n gpg --allow-secret-key-import --import duplicity-backup-sign-secret.key.txt\n\nAfter your key(s) has/have been succesfully imported, you should be able to restore your files.\n\nGood luck!"
|
||||
|
||||
if [ "$(echo "${DEST}" | cut -c 1,2)" = "gs" ]; then
|
||||
|
|
@ -410,6 +455,22 @@ else
|
|||
DEST_IS_S3=false
|
||||
fi
|
||||
|
||||
if [ "$(echo "${DEST}" | cut -c 1,4)" = "dpbx" ]; then
|
||||
DEST_IS_DPBX=true
|
||||
else
|
||||
DEST_IS_DPBX=false
|
||||
fi
|
||||
|
||||
if [ "$(echo "${DEST}" | cut -c 1,2)" = "b2" ]; then
|
||||
DEST_IS_B2=true
|
||||
B2CMD="$(which b2)"
|
||||
if [ ! -x "${B2CMD}" ]; then
|
||||
echo "${NO_B2CMD}"; B2CMD_AVAIL=false
|
||||
fi
|
||||
else
|
||||
DEST_IS_B2=false
|
||||
fi
|
||||
|
||||
config_sanity_fail()
|
||||
{
|
||||
EXPLANATION=$1
|
||||
|
|
@ -433,6 +494,8 @@ check_variables ()
|
|||
config_sanity_fail "An s3 DEST has been specified, but AWS_ACCESS_KEY_ID or AWS_SECRET_ACCESS_KEY have not been configured"
|
||||
[[ ( ${DEST_IS_GS} = true && (${GS_ACCESS_KEY_ID} = "foobar_gcs_key_id" || ${GS_SECRET_ACCESS_KEY} = "foobar_gcs_secret_id" )) ]] && \
|
||||
config_sanity_fail "A Google Cloud Storage DEST has been specified, but GS_ACCESS_KEY_ID or GS_SECRET_ACCESS_KEY have not been configured"
|
||||
[[ ( ${DEST_IS_DPBX} = true && (${DPBX_ACCESS_TOKEN} = "foobar_dropbox_access_token" )) ]] && \
|
||||
config_sanity_fail "A Dropbox DEST has been specified, but DPBX_ACCESS_TOKEN has not been configured"
|
||||
[[ ! -z "${INCEXCFILE}" && ! -f ${INCEXCFILE} ]] && config_sanity_fail "The specified INCEXCFILE ${INCEXCFILE} does not exists"
|
||||
}
|
||||
|
||||
|
|
@ -475,7 +538,7 @@ email_logfile()
|
|||
if [ ! -x "${MAILCMD}" ]; then
|
||||
echo -e "Email couldn't be sent. ${MAIL} not available." >&2
|
||||
else
|
||||
EMAIL_SUBJECT=${EMAIL_SUBJECT:="duplicity-backup ${BACKUP_STATUS:-"ERROR"} [${HOSTNAME}] ${LOG_FILE}"}
|
||||
EMAIL_SUBJECT=${EMAIL_SUBJECT:="duplicity-backup ${BACKUP_STATUS:-"ERROR"} (${HOSTNAME}) ${LOG_FILE}"}
|
||||
case ${MAIL} in
|
||||
ssmtp)
|
||||
mailcmd_ssmtp;;
|
||||
|
|
@ -508,21 +571,34 @@ email_logfile()
|
|||
|
||||
send_notification()
|
||||
{
|
||||
NOTIFICATION_CONTENT="duplicity-backup ${BACKUP_STATUS:-"ERROR"} [${HOSTNAME}] - \`${LOGFILE}\`"
|
||||
if [ ! -z "${NOTIFICATION_SERVICE}" ]; then
|
||||
echo "-----------[ Notification Request ]-----------"
|
||||
NOTIFICATION_CONTENT="duplicity-backup ${BACKUP_STATUS:-"ERROR"} [${HOSTNAME}] - \`${LOGFILE}\`"
|
||||
|
||||
if [ "${NOTIFICATION_SERVICE}" = "slack" ]; then
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"text\": \"${NOTIFICATION_CONTENT}\", \"channel\": \"${SLACK_CHANNEL}\", \"username\": \"${SLACK_USERNAME}\", \"icon_emoji\": \":${SLACK_EMOJI}:\"}" "${SLACK_HOOK_URL}"
|
||||
echo -e "Slack notification sent to channel ${SLACK_CHANNEL}"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "ifttt" ]; then
|
||||
curl -X POST -H 'Content-type: application/json' --data "{\"value1\": \"${NOTIFICATION_CONTENT}\", \"value2\": \"${IFTTT_VALUE2}\"}" "${IFTTT_HOOK_URL}"
|
||||
echo -e "IFTTT notification sent to Maker channel event ${IFTTT_EVENT}"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "pushover" ]; then
|
||||
curl -s \
|
||||
-F "token=${PUSHOVER_TOKEN}" \
|
||||
-F "user=${PUSHOVER_USER}" \
|
||||
-F "message=${NOTIFICATION_CONTENT}" \
|
||||
https://api.pushover.net/1/messages
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "telegram" ]; then
|
||||
curl -s --max-time 10 -d "chat_id=${TELEGRAM_CHATID}&disable_web_page_preview=1&text=${NOTIFICATION_CONTENT}" "https://api.telegram.org/bot${TELEGRAM_KEY}/sendMessage" >/dev/null
|
||||
fi
|
||||
|
||||
echo -e "\n----------------------------------------------\n"
|
||||
|
||||
if [ "${NOTIFICATION_SERVICE}" = "slack" ]; then
|
||||
echo -e "Slack notification sent to channel ${SLACK_CHANNEL}"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "ifttt" ]; then
|
||||
echo -e "IFTTT notification sent to Maker channel event ${IFTTT_EVENT}"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "pushover" ]; then
|
||||
echo -e "Pushover notification sent"
|
||||
elif [ "${NOTIFICATION_SERVICE}" = "telegram" ]; then
|
||||
echo -e "Telegram notification sent"
|
||||
fi
|
||||
fi
|
||||
}
|
||||
|
|
@ -612,7 +688,7 @@ get_remote_file_size()
|
|||
;;
|
||||
"fi")
|
||||
FRIENDLY_TYPE_NAME="File"
|
||||
TMPDEST=$(echo "${DEST}" | cut -c 6-)
|
||||
TMPDEST="${DEST#file://*}"
|
||||
SIZE=$(du -hs "${TMPDEST}" | awk '{print $1}')
|
||||
;;
|
||||
"gs")
|
||||
|
|
@ -626,7 +702,7 @@ get_remote_file_size()
|
|||
"s3")
|
||||
FRIENDLY_TYPE_NAME="Amazon S3"
|
||||
if ${S3CMD_AVAIL} ; then
|
||||
TMPDEST=$(echo "${DEST}" | cut -c 11-)
|
||||
TMPDEST=$(echo "${DEST}" | cut -f 3- -d /)
|
||||
dest_scheme=$(echo "${DEST}" | cut -f -1 -d :)
|
||||
if [ "$dest_scheme" = "s3" ]; then
|
||||
# Strip off the host name, too.
|
||||
|
|
@ -641,6 +717,33 @@ get_remote_file_size()
|
|||
fi
|
||||
fi
|
||||
;;
|
||||
"b2")
|
||||
FRIENDLY_TYPE_NAME="Backblaze B2"
|
||||
if ${B2CMD_AVAIL}; then
|
||||
if [[ -n ${FTP_PASSWORD} ]]; then
|
||||
APP_KEY=${FTP_PASSWORD}
|
||||
else
|
||||
APP_KEY=$(echo "${DEST}" | cut -d":" -f 3 | cut -d"@" -f 1)
|
||||
fi
|
||||
ACC_ID=$(echo "${DEST}" | cut -d"/" -f 3 | cut -d"@" -f 1 | cut -d ":" -f 1)
|
||||
BUCKET=$(echo "${DEST}" | cut -d"@" -f2 | cut -d"/" -f1)
|
||||
if [[ -z ${APP_KEY} ]] || [[ -z ${ACC_ID} ]]; then
|
||||
SIZE="-b2 authentication wrong-"
|
||||
return
|
||||
fi
|
||||
if [[ -z ${BUCKET} ]]; then
|
||||
SIZE="-b2 bucket wrong-"
|
||||
return
|
||||
fi
|
||||
if [[ $(${B2CMD} authorize-account "${ACC_ID}" "${APP_KEY}" >/dev/null 2>&1) -ne 0 ]]; then
|
||||
SIZE="-b2 authentication wrong-"
|
||||
return
|
||||
fi
|
||||
SIZE=$(${B2CMD} ls --long "${BUCKET}" | awk '{ print $5 }' | paste -sd+ | bc | numfmt --to=iec)
|
||||
else
|
||||
SIZE="-b2 not found in PATH-"
|
||||
fi
|
||||
;;
|
||||
*)
|
||||
# not yet available for the other backends
|
||||
FRIENDLY_TYPE_NAME=""
|
||||
|
|
@ -651,7 +754,7 @@ get_remote_file_size()
|
|||
echo -e "${SIZE}\t${FRIENDLY_TYPE_NAME} type backend"
|
||||
else
|
||||
echo "Destination disk use information is currently only available for the following storage backends:"
|
||||
echo "File, SSH, Amazon S3 and Google Cloud"
|
||||
echo "File, SSH, Amazon S3, Google Cloud and Backblaze B2"
|
||||
fi
|
||||
echo
|
||||
}
|
||||
|
|
@ -687,7 +790,11 @@ include_exclude()
|
|||
|
||||
# Include/Exclude globbing filelist
|
||||
if [ "${INCEXCFILE}" != '' ]; then
|
||||
TMP=" --include-globbing-filelist '${INCEXCFILE}'"
|
||||
if [ ${LT07} -eq 1 ]; then
|
||||
TMP=" --include-globbing-filelist '${INCEXCFILE}'"
|
||||
else
|
||||
TMP=" --include-filelist '${INCEXCFILE}'"
|
||||
fi
|
||||
INCLUDE=${INCLUDE}${TMP}
|
||||
fi
|
||||
|
||||
|
|
@ -733,7 +840,6 @@ duplicity_backup()
|
|||
{
|
||||
{
|
||||
eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
|
||||
"${STORAGECLASS}" \
|
||||
"${ENCRYPT}" \
|
||||
"${EXCLUDE}" \
|
||||
"${INCLUDE}" \
|
||||
|
|
@ -748,6 +854,7 @@ duplicity_cleanup_failed()
|
|||
{
|
||||
{
|
||||
eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
|
||||
"${ENCRYPT}" \
|
||||
"${DEST}"
|
||||
} || {
|
||||
BACKUP_ERROR=1
|
||||
|
|
@ -833,10 +940,13 @@ backup_this_script()
|
|||
GPG_TTY=$(tty)
|
||||
export GPG_TTY
|
||||
if [ "${GPG_ENC_KEY}" = "${GPG_SIGN_KEY}" ]; then
|
||||
gpg -a --export-secret-keys "${KEYRING}" "${GPG_ENC_KEY}" > "${TMPDIR}"/duplicity-backup-encryption-and-sign-secret.key.txt
|
||||
# shellcheck disable=SC2086
|
||||
gpg -a --export-secret-keys ${KEYRING} ${GPG_ENC_KEY} > "${TMPDIR}"/duplicity-backup-encryption-and-sign-secret.key.txt
|
||||
else
|
||||
gpg -a --export-secret-keys "${KEYRING}" "${GPG_ENC_KEY}" > "${TMPDIR}"/duplicity-backup-encryption-secret.key.txt
|
||||
gpg -a --export-secret-keys "${KEYRING}" "${GPG_SIGN_KEY}" > "${TMPDIR}"/duplicity-backup-sign-secret.key.txt
|
||||
# shellcheck disable=SC2086
|
||||
gpg -a --export-secret-keys ${KEYRING} ${GPG_ENC_KEY} > "${TMPDIR}"/duplicity-backup-encryption-secret.key.txt
|
||||
# shellcheck disable=SC2086
|
||||
gpg -a --export-secret-keys ${KEYRING} ${GPG_SIGN_KEY} > "${TMPDIR}"/duplicity-backup-sign-secret.key.txt
|
||||
fi
|
||||
fi
|
||||
|
||||
|
|
@ -858,6 +968,11 @@ check_variables
|
|||
|
||||
echo -e "-------- START DUPLICITY-BACKUP SCRIPT for ${HOSTNAME} --------\n" >&5
|
||||
|
||||
echo -e "-------[ Program versions ]-------"
|
||||
echo -e "duplicity-backup.sh ${DBSH_VERSION}"
|
||||
echo -e "duplicity ${DUPLICITY_VERSION}"
|
||||
echo -e "----------------------------------\n"
|
||||
|
||||
get_lock
|
||||
|
||||
INCLUDE=
|
||||
|
|
@ -904,7 +1019,7 @@ case "${COMMAND}" in
|
|||
OPTION="cleanup"
|
||||
|
||||
if [ -z "${DRY_RUN}" ]; then
|
||||
STATIC_OPTIONS="--force"
|
||||
STATIC_OPTIONS="${STATIC_OPTIONS} --force"
|
||||
fi
|
||||
|
||||
echo -e "-------[ Cleaning up Destination ]-------\n"
|
||||
|
|
@ -1023,6 +1138,10 @@ esac
|
|||
|
||||
echo -e "--------- END DUPLICITY-BACKUP SCRIPT ---------\n" >&5
|
||||
|
||||
if [ "${USAGE}" ]; then
|
||||
exit 0
|
||||
fi
|
||||
|
||||
if [ "${BACKUP_ERROR}" ]; then
|
||||
BACKUP_STATUS="ERROR"
|
||||
else
|
||||
|
|
@ -1047,6 +1166,11 @@ unset AWS_ACCESS_KEY_ID
|
|||
unset AWS_SECRET_ACCESS_KEY
|
||||
unset GS_ACCESS_KEY_ID
|
||||
unset GS_SECRET_ACCESS_KEY
|
||||
unset SWIFT_USERNAME
|
||||
unset SWIFT_PASSWORD
|
||||
unset SWIFT_AUTHURL
|
||||
unset SWIFT_AUTHVERSION
|
||||
unset DPBX_ACCESS_TOKEN
|
||||
unset PASSPHRASE
|
||||
unset SIGN_PASSPHRASE
|
||||
unset FTP_PASSWORD
|
||||
|
|
|
|||
Loading…
Reference in a new issue