Compare commits

..

No commits in common. "dev" and "v1.3.0" have entirely different histories.
dev ... v1.3.0

6 changed files with 56 additions and 203 deletions

View file

@ -3,8 +3,12 @@ language: bash
# Use container-based infrastructure for quicker build start-up # Use container-based infrastructure for quicker build start-up
sudo: false sudo: false
before_script: addons:
- shellcheck --version apt:
sources:
- debian-sid
packages:
- shellcheck
script: script:
- shellcheck -e SC2034 duplicity-backup.sh duplicity-backup.conf.example - shellcheck -e SC2034 duplicity-backup.sh duplicity-backup.conf.example

View file

@ -1,31 +1,6 @@
vX.X.X (unreleased) vX.X.X (unreleased)
=================== ===================
* Placeholder for next release
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) v1.3.0 (2016-10-23)
=================== ===================

View file

@ -31,7 +31,7 @@ This means the following:
## Contributing ## Contributing
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. 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 latests 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. 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.
@ -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`. 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 independent 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 independant of the previous one, just create another topic branch based on master (`git checkout -b my-fix-2 upstream/dev`)
## Installation ## Installation
@ -68,23 +68,20 @@ You can clone the repository (which makes it easy to get future updates):
git clone https://github.com/zertrin/duplicity-backup.sh.git duplicity-backup git clone https://github.com/zertrin/duplicity-backup.sh.git duplicity-backup
If you prefer the stable (but old) version do: If you prefer the stable version do:
git checkout stable git checkout stable
... or if you want the normal version, then: ... or if you want the latest version (might still have bugs), then:
git checkout master git checkout master
... 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 if you like living on the edge, you can stay at the development version which is automatically cloned.
Or just download the ZIP file: Or just download the ZIP file:
| Version | Download link | * For the stable branch: https://github.com/zertrin/duplicity-backup.sh/archive/stable.zip
|---------------|-------------------------------------------------------------------| * For the normal branch: https://github.com/zertrin/duplicity-backup.sh/archive/master.zip
| 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 ### 2. Configure the script
@ -97,7 +94,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). 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: 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)_ * 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. 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.
@ -123,13 +120,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. 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.
There are many ways to do so, here are some examples (adapt the path to your actual files): Thare 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 diff duplicity-backup.conf.example /etc/duplicity-backup.conf
vimdiff duplicity-backup.conf.example /etc/duplicity-backup.conf vimdiff duplicity-backup.conf.example /etc/duplicity-backup.conf
## Dependencies ## Dependancies
* [duplicity](http://duplicity.nongnu.org/) * [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) * 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)
@ -139,9 +136,6 @@ There 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`* For the [Amazon S3](https://aws.amazon.com/s3/) storage backend *`optional`*
* [s3cmd](http://s3tools.org/s3cmd) *`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`* 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) * [boto](https://github.com/boto/boto) (may already have been installed with duplicity)
* [gsutil](https://cloud.google.com/storage/docs/gsutil) *`optional`* * [gsutil](https://cloud.google.com/storage/docs/gsutil) *`optional`*
@ -252,13 +246,8 @@ Note that the commands `--restore-file` and `--restore-dir` are equivalent.
## Known issues ## 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` 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 ## Troubleshooting

1
VERSION Normal file
View file

@ -0,0 +1 @@
v1.3.0

View file

@ -2,7 +2,7 @@
# #
# Copyright (c) 2008-2010 Damon Timm. # Copyright (c) 2008-2010 Damon Timm.
# Copyright (c) 2010 Mario Santagiuliana. # Copyright (c) 2010 Mario Santagiuliana.
# Copyright (c) 2012-2018 Marc Gallet. # Copyright (c) 2012-2016 Marc Gallet.
# #
# This program is free software: you can redistribute it and/or modify it under # 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 # the terms of the GNU General Public License as published by the Free Software
@ -75,7 +75,7 @@
# This can be / or somewhere else -- I use /home/ because all the # This can be / or somewhere else -- I use /home/ because all the
# directories that I want to backup start with /home/. # directories that I want to backup start with /home/.
# #
ROOT='/home' ROOT="/home"
# Set hostname for this duplicity instance, useful for e-mail reports # Set hostname for this duplicity instance, useful for e-mail reports
# #
@ -108,14 +108,13 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
#DEST="ftpes://user[:password]@other.host[:port]/some_dir" #DEST="ftpes://user[:password]@other.host[:port]/some_dir"
#DEST="rsync://user@host.com[:port]//absolute_path" #DEST="rsync://user@host.com[:port]//absolute_path"
#DEST="scp://user[:password]@other.host[:port]/[/]some_dir" #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="sftp://user[:password]@other.host[:port]/[/]some_dir"
#DEST="file:///home/foobar_user_name/new-backup-test/" #DEST="file:///home/foobar_user_name/new-backup-test/"
#DEST="imap[s]://user[:password]@host.com[/from_address_prefix]" #DEST="imap[s]://user[:password]@host.com[/from_address_prefix]"
#DEST="webdav[s]://user[:password]@other.host[:port]/some_dir" #DEST="webdav[s]://user[:password]@other.host[:port]/some_dir"
#DEST="gdocs://foobar_google_account/some_dir" #DEST="gdocs://foobar_google_account/some_dir"
#DEST="swift://foobar_swift_container/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"
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -129,7 +128,7 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
# setting it in the backend url (which might be readable in the operating # setting it in the backend url (which might be readable in the operating
# systems process listing to other users on the same machine)." # systems process listing to other users on the same machine)."
# #
#FTP_PASSWORD='password' #FTP_PASSWORD="password"
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -174,13 +173,6 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
#SWIFT_AUTHURL="foobar_swift_authurl" #SWIFT_AUTHURL="foobar_swift_authurl"
#SWIFT_AUTHVERSION="2" #SWIFT_AUTHVERSION="2"
# ------------------------------------------------------------------------------
# DROPBOX INFORMATION
# ------------------------------------------------------------------------------
# Uncomment these lines if you're using Dropbox
#
#DPBX_ACCESS_TOKEN="foobar_dropbox_access_token"
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
# INCLUDE LIST OF DIRECTORIES # INCLUDE LIST OF DIRECTORIES
@ -190,15 +182,15 @@ DEST="s3+http://foobar-backup-bucket/backup-folder/"
# #
# Here is an example with multiple locations: # Here is an example with multiple locations:
# #
#INCLIST=( '/home/*/Documents' \ #INCLIST=( "/home/*/Documents" \
# '/home/*/Projects' \ # "/home/*/Projects" \
# '/home/*/logs' \ # "/home/*/logs" \
# '/home/www/mysql-backups' \ # "/home/www/mysql-backups" \
# ) # )
# #
# Simpler example with one location: # Simpler example with one location:
INCLIST=( '/home/foobar_user_name/Documents/' ) INCLIST=( "/home/foobar_user_name/Documents/" )
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -210,18 +202,18 @@ INCLIST=( '/home/foobar_user_name/Documents/' )
# #
# Here is an example with multiple locations: # Here is an example with multiple locations:
# #
#EXCLIST=( '/home/*/Trash' \ #EXCLIST=( "/home/*/Trash" \
# '/home/*/Projects/Completed' \ # "/home/*/Projects/Completed" \
# '/**.DS_Store' \ # "/**.DS_Store" \
# '/**Icon?' \ # "/**Icon?" \
# '/**.AppleDouble' \ # "/**.AppleDouble" \
# ) # )
# #
# If you don't want to exclude anything, use EXCLIST=() # If you don't want to exclude anything, use EXCLIST=()
# #
# Simpler example with one location. Adapt it to your needs. # 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" )
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------
@ -268,9 +260,9 @@ ENCRYPTION='yes'
# (your backups will be encrypted with this password) or is used # (your backups will be encrypted with this password) or is used
# for the "GPG_SIGN_KEY" (see below). # for the "GPG_SIGN_KEY" (see below).
# Comment out if you aren't using encryption # Comment out if you aren't using encryption
# Note: if you have a ' in your passphrase, escape it accordingly. # Note: if you have a '$' in your passphrase, escape it with a '\'
PASSPHRASE='foobar_gpg_passphrase' PASSPHRASE="foobar_gpg_passphrase"
# Specify which GPG keys you would like to use (even if you have only one). # 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 # If you are running this from a cron, it is highly recommended to create separate
@ -427,7 +419,7 @@ MAIL="mailx" # default command for Linux mail
# Third-party notification services. If NOTIFICATION_SERVICE is not provided, no # Third-party notification services. If NOTIFICATION_SERVICE is not provided, no
# notifications will be sent. # notifications will be sent.
# Possible values for NOTIFICATION_SERVICE are: slack, pushover, ifttt, telegram # Possible values for NOTIFICATION_SERVICE are: slack, pushover, ifttt
NOTIFICATION_SERVICE="" NOTIFICATION_SERVICE=""
NOTIFICATION_FAILURE_ONLY="yes" # send notifications only if there was an error while creating backup NOTIFICATION_FAILURE_ONLY="yes" # send notifications only if there was an error while creating backup
@ -447,10 +439,6 @@ 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_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) 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 # TROUBLESHOOTING
# ------------------------------------------------------------------------------ # ------------------------------------------------------------------------------

View file

@ -2,7 +2,7 @@
# #
# Copyright (c) 2008-2010 Damon Timm. # Copyright (c) 2008-2010 Damon Timm.
# Copyright (c) 2010 Mario Santagiuliana. # Copyright (c) 2010 Mario Santagiuliana.
# Copyright (c) 2012-2018 Marc Gallet. # Copyright (c) 2012-2016 Marc Gallet.
# #
# This program is free software: you can redistribute it and/or modify it under # 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 # the terms of the GNU General Public License as published by the Free Software
@ -45,8 +45,6 @@ CONFIG="duplicity-backup.conf"
# Script Happens Below This Line - Shouldn't Require Editing # # Script Happens Below This Line - Shouldn't Require Editing #
############################################################## ##############################################################
DBSH_VERSION="v1.6.0"
# make a backup of stdout and stderr for later # make a backup of stdout and stderr for later
exec 6>&1 exec 6>&1
exec 7>&2 exec 7>&2
@ -109,32 +107,12 @@ if [ ! -x "${DUPLICITY}" ]; then
exit 1 exit 1
fi fi
DUPLICITY_VERSION=$(${DUPLICITY} --version)
DUPLICITY_VERSION=${DUPLICITY_VERSION//[^0-9\.]/}
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(){ version(){
echo "duplicity-backup.sh ${DBSH_VERSION}" # Read the version string from the file VERSION
echo "duplicity ${DUPLICITY_VERSION}" VERSION=$(<VERSION)
echo "duplicity-backup.sh ${VERSION}"
${DUPLICITY} --version
exit 0 exit 0
} }
@ -191,7 +169,7 @@ while getopts ":c:t:bfvelsqndhV-:" opt; do
QUIET=1 QUIET=1
;; ;;
dry-run) dry-run)
DRY_RUN="--dry-run" DRY_RUN="--dry-run "
;; ;;
debug) debug)
ECHO=$(which echo) ECHO=$(which echo)
@ -218,7 +196,7 @@ while getopts ":c:t:bfvelsqndhV-:" opt; do
l) COMMAND="list-current-files";; l) COMMAND="list-current-files";;
s) COMMAND="collection-status";; s) COMMAND="collection-status";;
q) QUIET=1;; q) QUIET=1;;
n) DRY_RUN="--dry-run";; # dry run n) DRY_RUN="--dry-run ";; # dry run
d) ECHO=$(which echo);; # debug d) ECHO=$(which echo);; # debug
h) h)
usage usage
@ -305,7 +283,7 @@ fi
# fd1 is stdout and is always logged but only shown if not QUIET # fd1 is stdout and is always logged but only shown if not QUIET
# fd2 is stderr and is always shown on screen and logged # fd2 is stderr and is always shown on screen and logged
# fd3 is like stdout but always shown on screen (for interactive prompts) # fd3 is like stdout but always shown on screen (for interactive prompts)
# fd4 is always shown on screen but never logged (for the usage text) # fd4 is always shown on sceen but never logged (for the usage text)
# fd5 is never shown on screen but always logged (for delimiters in the log) # fd5 is never shown on screen but always logged (for delimiters in the log)
# #
@ -342,13 +320,7 @@ fi
# ------------------------- Setting up variables ------------------------ # ------------------------- Setting up variables ------------------------
if [ -n "${DRY_RUN}" ]; then STATIC_OPTIONS="${DRY_RUN}${STATIC_OPTIONS}"
STATIC_OPTIONS="${DRY_RUN} ${STATIC_OPTIONS}"
fi
if [ -n "${STORAGECLASS}" ]; then
STATIC_OPTIONS="${STATIC_OPTIONS} ${STORAGECLASS}"
fi
SIGN_PASSPHRASE=${PASSPHRASE} SIGN_PASSPHRASE=${PASSPHRASE}
@ -360,7 +332,6 @@ export SWIFT_USERNAME
export SWIFT_PASSWORD export SWIFT_PASSWORD
export SWIFT_AUTHURL export SWIFT_AUTHURL
export SWIFT_AUTHVERSION export SWIFT_AUTHVERSION
export DPBX_ACCESS_TOKEN
export PASSPHRASE export PASSPHRASE
export SIGN_PASSPHRASE export SIGN_PASSPHRASE
@ -410,9 +381,6 @@ NO_S3CMD_CFG="WARNING: s3cmd is not configured, run 's3cmd --configure' \
in order to retrieve remote file size information. Remote file \ in order to retrieve remote file size information. Remote file \
size information unavailable." 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!" 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 if [ "$(echo "${DEST}" | cut -c 1,2)" = "gs" ]; then
@ -455,22 +423,6 @@ else
DEST_IS_S3=false DEST_IS_S3=false
fi 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() config_sanity_fail()
{ {
EXPLANATION=$1 EXPLANATION=$1
@ -494,8 +446,6 @@ 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" 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" )) ]] && \ [[ ( ${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" 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" [[ ! -z "${INCEXCFILE}" && ! -f ${INCEXCFILE} ]] && config_sanity_fail "The specified INCEXCFILE ${INCEXCFILE} does not exists"
} }
@ -538,7 +488,7 @@ email_logfile()
if [ ! -x "${MAILCMD}" ]; then if [ ! -x "${MAILCMD}" ]; then
echo -e "Email couldn't be sent. ${MAIL} not available." >&2 echo -e "Email couldn't be sent. ${MAIL} not available." >&2
else 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 case ${MAIL} in
ssmtp) ssmtp)
mailcmd_ssmtp;; mailcmd_ssmtp;;
@ -571,34 +521,21 @@ email_logfile()
send_notification() send_notification()
{ {
if [ ! -z "${NOTIFICATION_SERVICE}" ]; then
echo "-----------[ Notification Request ]-----------"
NOTIFICATION_CONTENT="duplicity-backup ${BACKUP_STATUS:-"ERROR"} [${HOSTNAME}] - \`${LOGFILE}\`" NOTIFICATION_CONTENT="duplicity-backup ${BACKUP_STATUS:-"ERROR"} [${HOSTNAME}] - \`${LOGFILE}\`"
if [ ! -z "${NOTIFICATION_SERVICE}" ]; then
if [ "${NOTIFICATION_SERVICE}" = "slack" ]; then 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}" 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 elif [ "${NOTIFICATION_SERVICE}" = "ifttt" ]; then
curl -X POST -H 'Content-type: application/json' --data "{\"value1\": \"${NOTIFICATION_CONTENT}\", \"value2\": \"${IFTTT_VALUE2}\"}" "${IFTTT_HOOK_URL}" 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 elif [ "${NOTIFICATION_SERVICE}" = "pushover" ]; then
curl -s \ curl -s \
-F "token=${PUSHOVER_TOKEN}" \ -F "token=${PUSHOVER_TOKEN}" \
-F "user=${PUSHOVER_USER}" \ -F "user=${PUSHOVER_USER}" \
-F "message=${NOTIFICATION_CONTENT}" \ -F "message=${NOTIFICATION_CONTENT}" \
https://api.pushover.net/1/messages 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" echo -e "Pushover notification sent"
elif [ "${NOTIFICATION_SERVICE}" = "telegram" ]; then
echo -e "Telegram notification sent"
fi fi
fi fi
} }
@ -688,7 +625,7 @@ get_remote_file_size()
;; ;;
"fi") "fi")
FRIENDLY_TYPE_NAME="File" FRIENDLY_TYPE_NAME="File"
TMPDEST="${DEST#file://*}" TMPDEST=$(echo "${DEST}" | cut -c 6-)
SIZE=$(du -hs "${TMPDEST}" | awk '{print $1}') SIZE=$(du -hs "${TMPDEST}" | awk '{print $1}')
;; ;;
"gs") "gs")
@ -702,7 +639,7 @@ get_remote_file_size()
"s3") "s3")
FRIENDLY_TYPE_NAME="Amazon S3" FRIENDLY_TYPE_NAME="Amazon S3"
if ${S3CMD_AVAIL} ; then if ${S3CMD_AVAIL} ; then
TMPDEST=$(echo "${DEST}" | cut -f 3- -d /) TMPDEST=$(echo "${DEST}" | cut -c 11-)
dest_scheme=$(echo "${DEST}" | cut -f -1 -d :) dest_scheme=$(echo "${DEST}" | cut -f -1 -d :)
if [ "$dest_scheme" = "s3" ]; then if [ "$dest_scheme" = "s3" ]; then
# Strip off the host name, too. # Strip off the host name, too.
@ -717,33 +654,6 @@ get_remote_file_size()
fi fi
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 # not yet available for the other backends
FRIENDLY_TYPE_NAME="" FRIENDLY_TYPE_NAME=""
@ -754,7 +664,7 @@ get_remote_file_size()
echo -e "${SIZE}\t${FRIENDLY_TYPE_NAME} type backend" echo -e "${SIZE}\t${FRIENDLY_TYPE_NAME} type backend"
else else
echo "Destination disk use information is currently only available for the following storage backends:" echo "Destination disk use information is currently only available for the following storage backends:"
echo "File, SSH, Amazon S3, Google Cloud and Backblaze B2" echo "File, SSH, Amazon S3 and Google Cloud"
fi fi
echo echo
} }
@ -790,11 +700,7 @@ include_exclude()
# Include/Exclude globbing filelist # Include/Exclude globbing filelist
if [ "${INCEXCFILE}" != '' ]; then if [ "${INCEXCFILE}" != '' ]; then
if [ ${LT07} -eq 1 ]; then
TMP=" --include-globbing-filelist '${INCEXCFILE}'" TMP=" --include-globbing-filelist '${INCEXCFILE}'"
else
TMP=" --include-filelist '${INCEXCFILE}'"
fi
INCLUDE=${INCLUDE}${TMP} INCLUDE=${INCLUDE}${TMP}
fi fi
@ -840,6 +746,7 @@ duplicity_backup()
{ {
{ {
eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \ eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
"${STORAGECLASS}" \
"${ENCRYPT}" \ "${ENCRYPT}" \
"${EXCLUDE}" \ "${EXCLUDE}" \
"${INCLUDE}" \ "${INCLUDE}" \
@ -854,7 +761,6 @@ duplicity_cleanup_failed()
{ {
{ {
eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \ eval "${ECHO}" "${DUPLICITY}" "${OPTION}" "${VERBOSITY}" "${STATIC_OPTIONS}" \
"${ENCRYPT}" \
"${DEST}" "${DEST}"
} || { } || {
BACKUP_ERROR=1 BACKUP_ERROR=1
@ -968,11 +874,6 @@ check_variables
echo -e "-------- START DUPLICITY-BACKUP SCRIPT for ${HOSTNAME} --------\n" >&5 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 get_lock
INCLUDE= INCLUDE=
@ -1019,7 +920,7 @@ case "${COMMAND}" in
OPTION="cleanup" OPTION="cleanup"
if [ -z "${DRY_RUN}" ]; then if [ -z "${DRY_RUN}" ]; then
STATIC_OPTIONS="${STATIC_OPTIONS} --force" STATIC_OPTIONS="--force"
fi fi
echo -e "-------[ Cleaning up Destination ]-------\n" echo -e "-------[ Cleaning up Destination ]-------\n"
@ -1166,11 +1067,6 @@ unset AWS_ACCESS_KEY_ID
unset AWS_SECRET_ACCESS_KEY unset AWS_SECRET_ACCESS_KEY
unset GS_ACCESS_KEY_ID unset GS_ACCESS_KEY_ID
unset GS_SECRET_ACCESS_KEY unset GS_SECRET_ACCESS_KEY
unset SWIFT_USERNAME
unset SWIFT_PASSWORD
unset SWIFT_AUTHURL
unset SWIFT_AUTHVERSION
unset DPBX_ACCESS_TOKEN
unset PASSPHRASE unset PASSPHRASE
unset SIGN_PASSPHRASE unset SIGN_PASSPHRASE
unset FTP_PASSWORD unset FTP_PASSWORD