Merge pull request #9 from zertrin/options-parsing
Merge branch "options-parsing" to "master" : Intelligent argument parsing added and possibility to specify the config file on the command line re-added.
This commit is contained in:
commit
f66427f209
3 changed files with 191 additions and 64 deletions
|
|
@ -1,3 +1,11 @@
|
|||
0.8 (05 August 2012)
|
||||
===================
|
||||
* Improved argument parsing. Now the script is insensitive to the order of appearance of the options and handles correctly optional options parameters
|
||||
* Re-added possibility to specify the config file on the command line, which is now the recommended way to do (facilitating script updates)
|
||||
* Added dry-run command line option (-n or --dry-run)
|
||||
* Added many short versions of long options (-b, -f, -v, -l, -s)
|
||||
* Fix "unary operator expected warning" in some rare cases
|
||||
|
||||
0.7.1 (9 July 2012)
|
||||
===================
|
||||
* Adding 'duplicity-backup.conf' to .gitignore
|
||||
|
|
|
|||
86
README
86
README
|
|
@ -2,13 +2,15 @@ ABOUT THIS SCRIPT
|
|||
=================
|
||||
|
||||
This bash script was designed to automate and simplify the remote backup process
|
||||
of duplicity on Amazon S3 primarily. Other backup destinations are possible.
|
||||
of duplicity on Amazon S3 primarily. Other backup destinations are possible
|
||||
(FTP, SFTP, SCP, rsync, file...), i.e. any of duplicity's supported outputs.
|
||||
|
||||
After your script is configured, you can easily backup, restore, verify and
|
||||
clean (either via cron or manually) your data without having to remember lots of
|
||||
different command options and passphrases.
|
||||
|
||||
Most importantly, you can easily backup the script and your gpg key in a
|
||||
convenient passphrase-encrypted file. This comes in in handy if/when your
|
||||
convenient passphrase-encrypted file. This comes in in handy if/when your
|
||||
machine ever does go belly up.
|
||||
|
||||
Optionally, you can set up an email address where the log file will be sent,
|
||||
|
|
@ -38,10 +40,10 @@ file, but make a copy of it and edit this one. Be sure to replace all the
|
|||
*foobar* values with your real ones. Almost every value needs to be configured
|
||||
in someway.
|
||||
|
||||
You can use multiple copies of the script with different settings for different
|
||||
backup scenarios. It is designed to run as a cron job and will log information
|
||||
to a text file (including remote file sizes, if you have s3cmd installed). Be
|
||||
sure to make the script executable (chmod +x) before you hit the gas.
|
||||
You can use one copy of the script with different settings for different backup
|
||||
scenarios. It is designed to run as a cron job and will log information to a
|
||||
text file (including remote file sizes, if you have s3cmd installed). Be sure to
|
||||
make the script executable (chmod +x) before you hit the gas.
|
||||
|
||||
REQUIREMENTS
|
||||
============
|
||||
|
|
@ -57,9 +59,47 @@ CONFIGURATION
|
|||
|
||||
The configuration takes place in a separate config file and is documented there.
|
||||
|
||||
The script looks for its configuration by reading the config file specified in
|
||||
the CONFIG parameter at the beggining of the script. Be sure to edit it to match
|
||||
the actual location of your config file.
|
||||
You want to copy duplicity-backup.conf.example to another place that suits your
|
||||
needs (for example /etc/duplicity-backup.conf)
|
||||
|
||||
The script looks for its configuration by reading the config file specified by
|
||||
the command line option -c or --config (see USAGE)
|
||||
|
||||
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 beggining of the script (defaults
|
||||
to "duplicity-backup.conf" in the script's directory).
|
||||
|
||||
So be sure either:
|
||||
- to specify the configuration file path on the command line [recommended]
|
||||
- or to edit the CONFIG parameter in thescript to match the actual location of
|
||||
your config file. [deprecated]
|
||||
|
||||
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.
|
||||
|
||||
USAGE
|
||||
=====
|
||||
|
||||
duplicity-backup.sh [options]
|
||||
|
||||
Options:
|
||||
-c, --config CONFIG_FILE specify the config file to use
|
||||
|
||||
-b, --backup runs an incremental backup
|
||||
-f, --full forces a full backup
|
||||
|
||||
-v, --verify verifies the backup
|
||||
--restore [PATH] restores the entire backup to [path]
|
||||
--restore-file [FILE_TO_RESTORE] [DESTINATION]
|
||||
restore a specific file
|
||||
|
||||
-l, --list-current-files lists the files currently backed up in the archive
|
||||
-s, --collection-status show all the backup sets in the archive
|
||||
|
||||
--backup-script automatically backup the script and secret key to
|
||||
the current working directory
|
||||
-n, --dry-run perform a trial run with no changes made
|
||||
|
||||
COMMON USAGE EXAMPLES
|
||||
=====================
|
||||
|
|
@ -68,36 +108,36 @@ COMMON USAGE EXAMPLES
|
|||
$ duplicity-backup.sh
|
||||
|
||||
* Run an incremental backup:
|
||||
$ duplicity-backup.sh --backup
|
||||
$ duplicity-backup.sh [-c config_file] --backup
|
||||
|
||||
* Force a one-off full backup:
|
||||
$ duplicity-backup.sh --full
|
||||
$ duplicity-backup.sh [-c config_file] --full
|
||||
|
||||
* Restore your entire backup:
|
||||
$ duplicity-backup.sh --restore
|
||||
$ duplicity-backup.sh [-c config_file] --restore
|
||||
You will be prompted for a restore directory
|
||||
|
||||
$ duplicity-backup.sh --restore /home/user/restore-folder
|
||||
$ duplicity-backup.sh [-c config_file] --restore /home/user/restore-folder
|
||||
You can also provide a restore folder on the command line.
|
||||
|
||||
* Restore a specific file in the backup:
|
||||
$ duplicity-backup.sh --restore-file
|
||||
$ duplicity-backup.sh [-c config_file] --restore-file
|
||||
You will be prompted for a file to restore to the current directory
|
||||
|
||||
$ duplicity-backup.sh --restore-file img/mom.jpg
|
||||
$ duplicity-backup.sh [-c config_file] --restore-file img/mom.jpg
|
||||
Restores the file img/mom.jpg to the current directory
|
||||
|
||||
$ duplicity-backup.sh --restore-file img/mom.jpg /home/user/i-love-mom.jpg
|
||||
$ duplicity-backup.sh [-c config_file] --restore-file img/mom.jpg /home/user/i-love-mom.jpg
|
||||
Restores the file img/mom.jpg to /home/user/i-love-mom.jpg
|
||||
|
||||
* List files in the remote archive
|
||||
$ duplicity-backup.sh --list-current-files
|
||||
$ duplicity-backup.sh [-c config_file] --list-current-files
|
||||
|
||||
* Verify the backup
|
||||
$ duplicity-backup.sh --verify
|
||||
$ duplicity-backup.sh [-c config_file] --verify
|
||||
|
||||
* Backup the script and gpg key (for safekeeping)
|
||||
$ duplicity-backup.sh --backup-script
|
||||
$ duplicity-backup.sh [-c config_file] --backup-script
|
||||
|
||||
TROUBLESHOOTING
|
||||
===============
|
||||
|
|
@ -107,9 +147,11 @@ 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, 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
|
||||
To see exactly what is happening when you run duplicity-backup, either pass the
|
||||
option -n or --dry-run 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.
|
||||
|
||||
|
|
|
|||
|
|
@ -27,20 +27,121 @@
|
|||
#
|
||||
# ---------------------------------------------------------------------------- #
|
||||
|
||||
# Set config file (don't forget to copy duplicity-backup.conf.example to
|
||||
# match that path)
|
||||
# Default config file (don't forget to copy duplicity-backup.conf.example to
|
||||
# match that path)
|
||||
# NOTE: It can be useful not to edit this script at all to ease future updates
|
||||
# so the config file can be specified directly on the command line too
|
||||
# with the -c option.
|
||||
CONFIG="duplicity-backup.conf"
|
||||
|
||||
##############################################################
|
||||
# Script Happens Below This Line - Shouldn't Require Editing #
|
||||
##############################################################
|
||||
|
||||
usage(){
|
||||
echo "USAGE:
|
||||
`basename $0` [options]
|
||||
|
||||
Options:
|
||||
-c, --config CONFIG_FILE specify the config file to use
|
||||
|
||||
-b, --backup runs an incremental backup
|
||||
-f, --full forces a full backup
|
||||
-v, --verify verifies the backup
|
||||
--restore [PATH] restores the entire backup to [path]
|
||||
--restore-file [FILE_TO_RESTORE] [DESTINATION]
|
||||
restore a specific file
|
||||
-l, --list-current-files lists the files currently backed up in the archive
|
||||
-s, --collection-status show all the backup sets in the archive
|
||||
--backup-script automatically backup the script and secret key to
|
||||
the current working directory
|
||||
-n, --dry-run perform a trial run with no changes made
|
||||
|
||||
CURRENT SCRIPT VARIABLES:
|
||||
========================
|
||||
DEST (backup destination) = ${DEST}
|
||||
INCLIST (directories included) = ${INCLIST[@]:0}
|
||||
EXCLIST (directories excluded) = ${EXCLIST[@]:0}
|
||||
ROOT (root directory of backup) = ${ROOT}
|
||||
LOGFILE (log file path) = ${LOGFILE}
|
||||
"
|
||||
}
|
||||
|
||||
# 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:bfvlsn-:" 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)
|
||||
-)
|
||||
case "$OPTARG" in
|
||||
# --restore [restore dest]
|
||||
restore)
|
||||
COMMAND=$OPTARG
|
||||
# We try to find the optional value [restore dest]
|
||||
if [ ! -z "${!OPTIND:0:1}" -a ! "${!OPTIND:0:1}" = "-" ]; then
|
||||
RESTORE_DEST=${!OPTIND}
|
||||
OPTIND=$(( $OPTIND + 1 )) # we found it, move forward in arg parsing
|
||||
fi
|
||||
;;
|
||||
# --restore-file [file to restore] [restore dest]
|
||||
restore-file)
|
||||
COMMAND=$OPTARG
|
||||
# We try to find the first optional value [file to restore]
|
||||
if [ ! -z "${!OPTIND:0:1}" -a ! "${!OPTIND:0:1}" = "-" ]; then
|
||||
FILE_TO_RESTORE=${!OPTIND}
|
||||
OPTIND=$(( $OPTIND + 1 )) # we found it, move forward in arg parsing
|
||||
else
|
||||
continue # no value for the restore-file option, skip the rest
|
||||
fi
|
||||
# We try to find the second optional value [restore dest]
|
||||
if [ ! -z "${!OPTIND:0:1}" -a ! "${!OPTIND:0:1}" = "-" ]; then
|
||||
RESTORE_DEST=${!OPTIND}
|
||||
OPTIND=$(( $OPTIND + 1 )) # we found it, move forward in arg parsing
|
||||
fi
|
||||
;;
|
||||
config) # set the config file from the command line
|
||||
# We try to find the config file
|
||||
if [ ! -z "${!OPTIND:0:1}" -a ! "${!OPTIND:0:1}" = "-" ]; then
|
||||
CONFIG=${!OPTIND}
|
||||
OPTIND=$(( $OPTIND + 1 )) # we found it, move forward in arg parsing
|
||||
fi
|
||||
;;
|
||||
dry-run)
|
||||
ECHO=$(which echo)
|
||||
;;
|
||||
*)
|
||||
COMMAND=$OPTARG
|
||||
;;
|
||||
esac
|
||||
;;
|
||||
# here are parsed the short options
|
||||
c) CONFIG=$OPTARG;; # set the config file from the command line
|
||||
b) COMMAND="backup";;
|
||||
f) COMMAND="full";;
|
||||
v) COMMAND="verify";;
|
||||
l) COMMAND="list-current-files";;
|
||||
s) COMMAND="collection-status";;
|
||||
n) ECHO=$(which echo);; # dry run
|
||||
:)
|
||||
echo "Option -$OPTARG requires an argument." >&2
|
||||
COMMAND=""
|
||||
;;
|
||||
\?)
|
||||
echo "Invalid option: -$OPTARG" >&2
|
||||
COMMAND=""
|
||||
;;
|
||||
esac
|
||||
done
|
||||
|
||||
# Read config file if specified
|
||||
if [ ! -z "$CONFIG" -a -f "$CONFIG" ];
|
||||
then
|
||||
. $CONFIG
|
||||
else
|
||||
echo "ERROR: can't find config file! (${CONFIG})" >&2
|
||||
usage
|
||||
exit 1
|
||||
fi
|
||||
|
||||
|
|
@ -72,7 +173,7 @@ NO_S3CMD_CFG="WARNING: s3cmd is not configured, run 's3cmd --configure' \
|
|||
in order to retrieve remote file size information. Remote file \
|
||||
size information unavailable."
|
||||
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 key (if you haven't already). The key is in this directory and the following command should do the trick:\n\ngpg --allow-secret-key-import --import duplicity-backup-secret.key.txt\n\nAfter your key as been succesfully imported, you should be able to restore your files.\n\nGood luck!"
|
||||
CONFIG_VAR_MSG="Oops!! ${0} was unable to run!\nWe are missing one or more important variables at the top of the script.\nCheck your configuration because it appears that something has not been set yet."
|
||||
CONFIG_VAR_MSG="Oops!! ${0} was unable to run!\nWe are missing one or more important variables in the configuration file.\nCheck your configuration because it appears that something has not been set yet."
|
||||
|
||||
if [ ! -x "$DUPLICITY" ]; then
|
||||
echo "ERROR: duplicity not installed, that's gotta happen first!" >&2
|
||||
|
|
@ -322,13 +423,13 @@ echo -e "-------- START DUPLICITY-BACKUP SCRIPT --------\n" >> ${LOGFILE}
|
|||
|
||||
get_lock
|
||||
|
||||
case "$1" in
|
||||
"--backup-script")
|
||||
case "$COMMAND" in
|
||||
"backup-script")
|
||||
backup_this_script
|
||||
exit
|
||||
;;
|
||||
|
||||
"--full")
|
||||
"full")
|
||||
OPTION="full"
|
||||
include_exclude
|
||||
duplicity_backup
|
||||
|
|
@ -336,7 +437,7 @@ case "$1" in
|
|||
get_file_sizes
|
||||
;;
|
||||
|
||||
"--verify")
|
||||
"verify")
|
||||
OLDROOT=${ROOT}
|
||||
ROOT=${DEST}
|
||||
DEST=${OLDROOT}
|
||||
|
|
@ -355,11 +456,11 @@ case "$1" in
|
|||
echo -e "Verify complete. Check the log file for results:\n>> ${LOGFILE}"
|
||||
;;
|
||||
|
||||
"--restore")
|
||||
"restore")
|
||||
ROOT=$DEST
|
||||
OPTION="restore"
|
||||
|
||||
if [[ ! "$2" ]]; then
|
||||
if [[ ! "$RESTORE_DEST" ]]; then
|
||||
echo "Please provide a destination path (eg, /home/user/dir):"
|
||||
read -e NEWDESTINATION
|
||||
DEST=$NEWDESTINATION
|
||||
|
|
@ -372,30 +473,28 @@ case "$1" in
|
|||
exit 1
|
||||
fi
|
||||
else
|
||||
DEST=$2
|
||||
DEST=$RESTORE_DEST
|
||||
fi
|
||||
|
||||
echo "Attempting to restore now ..."
|
||||
duplicity_backup
|
||||
;;
|
||||
|
||||
"--restore-file")
|
||||
"restore-file")
|
||||
ROOT=$DEST
|
||||
INCLUDE=
|
||||
EXCLUDE=
|
||||
EXLUDEROOT=
|
||||
OPTION=
|
||||
|
||||
if [[ ! "$2" ]]; then
|
||||
if [[ ! "$FILE_TO_RESTORE" ]]; then
|
||||
echo "Which file do you want to restore (eg, mail/letter.txt):"
|
||||
read -e FILE_TO_RESTORE
|
||||
echo
|
||||
else
|
||||
FILE_TO_RESTORE=$2
|
||||
fi
|
||||
|
||||
if [[ "$3" ]]; then
|
||||
DEST=$3
|
||||
if [[ "$RESTORE_DEST" ]]; then
|
||||
DEST=$RESTORE_DEST
|
||||
else
|
||||
DEST=$(basename $FILE_TO_RESTORE)
|
||||
fi
|
||||
|
|
@ -420,7 +519,7 @@ case "$1" in
|
|||
duplicity_backup
|
||||
;;
|
||||
|
||||
"--list-current-files")
|
||||
"list-current-files")
|
||||
OPTION="list-current-files"
|
||||
${DUPLICITY} ${OPTION} ${VERBOSITY} ${STATIC_OPTIONS} \
|
||||
$ENCRYPT \
|
||||
|
|
@ -428,7 +527,7 @@ case "$1" in
|
|||
echo -e "-------- END --------\n" >> ${LOGFILE}
|
||||
;;
|
||||
|
||||
"--collection-status")
|
||||
"collection-status")
|
||||
OPTION="collection-status"
|
||||
${DUPLICITY} ${OPTION} ${VERBOSITY} ${STATIC_OPTIONS} \
|
||||
$ENCRYPT \
|
||||
|
|
@ -436,7 +535,7 @@ case "$1" in
|
|||
echo -e "-------- END --------\n" >> ${LOGFILE}
|
||||
;;
|
||||
|
||||
"--backup")
|
||||
"backup")
|
||||
include_exclude
|
||||
duplicity_backup
|
||||
duplicity_cleanup
|
||||
|
|
@ -445,29 +544,7 @@ case "$1" in
|
|||
|
||||
*)
|
||||
echo -e "[Only show `basename $0` usage options]\n" >> ${LOGFILE}
|
||||
echo " USAGE:
|
||||
`basename $0` [options]
|
||||
|
||||
Options:
|
||||
--backup: runs an incremental backup
|
||||
--full: forces a full backup
|
||||
|
||||
--verify: verifies the backup
|
||||
--restore [path]: restores the entire backup
|
||||
--restore-file [file] [destination/filename]: restore a specific file
|
||||
--list-current-files: lists the files currently backed up in the archive
|
||||
--collection-status: show all the backup sets in the archive
|
||||
|
||||
--backup-script: automatically backup the script and secret key to the current working directory
|
||||
|
||||
CURRENT SCRIPT VARIABLES:
|
||||
========================
|
||||
DEST (backup destination) = ${DEST}
|
||||
INCLIST (directories included) = ${INCLIST[@]:0}
|
||||
EXCLIST (directories excluded) = ${EXCLIST[@]:0}
|
||||
ROOT (root directory of backup) = ${ROOT}
|
||||
LOGFILE (log file path) = ${LOGFILE}
|
||||
"
|
||||
usage
|
||||
;;
|
||||
esac
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue