First Commit
This commit is contained in:
21
LICENSE
Normal file
21
LICENSE
Normal file
@ -0,0 +1,21 @@
|
||||
The MIT License (MIT)
|
||||
|
||||
Copyright (c) 2015 Jonas Friedmann
|
||||
|
||||
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.
|
89
README.md
Normal file
89
README.md
Normal file
@ -0,0 +1,89 @@
|
||||
tar-multibackup
|
||||
===============
|
||||
Bash script to backup multiple folders and to clean up old backups based on a retention time. Features configurable post/pre-commands, tar excludes as well as backup retentions.
|
||||
|
||||
### Installation
|
||||
cd /usr/local/src
|
||||
git clone https://github.com/frdmn/tar-multibackup.git
|
||||
ln -sf /usr/local/src/tar-multibackup/multibackup /usr/local/bin/multibackup
|
||||
cp /usr/local/src/tar-multibackup/multibackup.conf ~/.multibackup.conf
|
||||
|
||||
### Configuration and usage
|
||||
|
||||
* `timestamp` = Format of the timestamp, used in the backup target filename
|
||||
* `backup_destination` = Directory which is used to store the archives/backups
|
||||
* `folders_to_backup` = Array of folders to backup
|
||||
* `backup_retention` = Retention time how long we should keep the backups
|
||||
* `pre_commands` = Array of commands that are executed before the backup starts (stop specific service)
|
||||
* `post_commands` = Array of commands that are executed after the backup finished (start specific service)
|
||||
* `tar_options` = Additional tar Options
|
||||
|
||||
### Environment configurations
|
||||
|
||||
* `DEBUG` = if set to "true", `set -x` will be set
|
||||
* `CONFIG` = if you want to use a different configuration file than the
|
||||
|
||||
Example:
|
||||
|
||||
CONFIG=/tmp/testbackup.conf DEBUG=true multibackup
|
||||
|
||||
#### Example configuration
|
||||
|
||||
In the example below you can find a `multibackup` configuration file to backup a productional [LiveConfig](http://www.liveconfig.com/) instance.
|
||||
|
||||
`vi ~/.multibackup.conf`
|
||||
|
||||
# Timestamp format, used in the backup target filename
|
||||
timestamp=$(date +%Y%m%d)
|
||||
|
||||
# Destination where you want to store your backups
|
||||
backup_destination="/var/backups"
|
||||
|
||||
# Folders to backup
|
||||
folders_to_backup=(
|
||||
"/etc"
|
||||
"/var/mail"
|
||||
"/var/www"
|
||||
"/var/lib/mysql"
|
||||
"/var/spool/cron"
|
||||
"/var/lib/liveconfig"
|
||||
)
|
||||
|
||||
# Files and folders that are excluded in the tar command
|
||||
tar_excludes=(
|
||||
"nginx-php-fcgi.sock"
|
||||
)
|
||||
|
||||
# Additional tar Options
|
||||
tar_options=()
|
||||
|
||||
# How long to you want to keep your backups (in days)
|
||||
backup_retention="+7"
|
||||
|
||||
# Commands that are executed before the backup started
|
||||
# (We have to make sure the liveconfig process is not running)
|
||||
# (otherwise the databases changes while we try to save it)
|
||||
pre_commands=(
|
||||
"service liveconfig stop"
|
||||
)
|
||||
|
||||
# Commands that are executed after the backup is completed
|
||||
# (To restart the liveconfig process again, once the backup is completed)
|
||||
post_commands=(
|
||||
"service liveconfig start"
|
||||
)
|
||||
|
||||
#### Cronjob setup
|
||||
|
||||
To make sure the backup is executed automatically and recurring, we're going to add a simple cronjob:
|
||||
|
||||
`vi /etc/cron.d/backup-liveconfig`
|
||||
|
||||
#
|
||||
# cronjob to backup LiveConfig, daily at 5:00 am
|
||||
#
|
||||
|
||||
0 5 * * * root /usr/local/bin/multibackup &>/dev/null
|
||||
|
||||
#### CREDITS
|
||||
This Backup Script is a fork of https://github.com/frdmn/tar-multibackup
|
178
multibackup
Normal file
178
multibackup
Normal file
@ -0,0 +1,178 @@
|
||||
#!/usr/bin/env bash
|
||||
|
||||
[[ -n "${DEBUG}" ]] && set -x
|
||||
|
||||
###
|
||||
# Configuration
|
||||
###
|
||||
|
||||
# Use "~/.multibackup" as default config, if $CONFIG is not specified
|
||||
CONFIG="${CONFIG:-${HOME}/.multibackup.conf}"
|
||||
|
||||
###
|
||||
# Functions
|
||||
###
|
||||
|
||||
# Color helpers
|
||||
color_red=$(tput setaf 1)
|
||||
color_yellow=$(tput setaf 3)
|
||||
color_green=$(tput setaf 2)
|
||||
color_reset=$(tput sgr0)
|
||||
|
||||
# Logging prefix helper
|
||||
prefix(){
|
||||
# Check if placeholders variables are given
|
||||
if [[ -n "${current_action}" && -n "${current_task}" && -n "${total_tasks}" ]]; then
|
||||
# Return prefix
|
||||
echo "[${current_action}] [${current_task}/${total_tasks}] "
|
||||
fi
|
||||
}
|
||||
|
||||
# Logging helpers
|
||||
debug() {
|
||||
echo "$(prefix)[DEBUG] $@ " 1>&2
|
||||
}
|
||||
|
||||
success() {
|
||||
echo "$(prefix)${color_green}[SUCCESS]${color_reset} $@" 1>&2
|
||||
}
|
||||
|
||||
info() {
|
||||
echo "$(prefix)${color_yellow}[INFO]${color_reset} $@" 1>&2
|
||||
}
|
||||
|
||||
error() {
|
||||
echo "$(prefix)${color_red}[ERROR]${color_reset} $@" 1>&2
|
||||
}
|
||||
|
||||
# Strip all redundant slashes in file paths
|
||||
strip_duplicate_slashes_in_path(){
|
||||
# Backup current shopt options
|
||||
shoptBackup=$(shopt -p)
|
||||
# Set extented globbing
|
||||
shopt -s extglob
|
||||
# Substitute input (turn multiple slashes into single one) and return
|
||||
echo "${@//+(\/)//}"
|
||||
# Restore shopt
|
||||
eval "$oldShoptOptions" &> /dev/null
|
||||
}
|
||||
|
||||
# Replace all slashes with dashes
|
||||
replace_slash_with_dash(){
|
||||
input="${@////-}" # replace all slashes with dashes
|
||||
input="${input/#-/}" # remove possible starting dash
|
||||
output="${input/%-/}" # as well as possible trailing dash
|
||||
echo "${output}"
|
||||
}
|
||||
|
||||
###
|
||||
# Logic
|
||||
###
|
||||
|
||||
# Check for config file then read and source
|
||||
if [[ -f "${CONFIG}" ]]; then
|
||||
. "${CONFIG}"
|
||||
else
|
||||
error "Couldn't find configuration file \"${CONFIG}\""
|
||||
exit 1
|
||||
fi
|
||||
|
||||
# Iterate through tar_excludes to create a "--exclude=XXX" combination string
|
||||
tar_exclude_parameters=()
|
||||
if [[ "${#tar_excludes[@]}" -ne 0 ]]; then
|
||||
# Run each pre command
|
||||
for parameter in "${tar_excludes[@]}"; do
|
||||
tar_exclude_parameters+=( "--exclude=${parameter}" )
|
||||
done
|
||||
fi
|
||||
|
||||
# Set prefix variables for pre-commands
|
||||
current_action="pre-command"
|
||||
current_task=1
|
||||
total_tasks="${#pre_commands[@]}"
|
||||
|
||||
# Iterate through pre_commnads
|
||||
if [[ "${#pre_commands[@]}" -ne 0 ]]; then
|
||||
info "Found pre commands..."
|
||||
# Run each pre command
|
||||
for pre_command in "${pre_commands[@]}"; do
|
||||
info "Running \"${pre_command}\":"
|
||||
eval "${pre_command}"
|
||||
# Check if pre command ran successfully
|
||||
if [[ $? -eq 0 ]]; then
|
||||
success "Pre command \"${pre_command}\" successfully completed!"
|
||||
else
|
||||
error "Pre command \"${pre_command}\" failed..."
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Set prefix variables for backup
|
||||
current_action="backup"
|
||||
current_task=1
|
||||
total_tasks="${#folders_to_backup[@]}"
|
||||
|
||||
# Iterate through "$folders_to_backup"
|
||||
for folder_to_backup in "${folders_to_backup[@]}"; do
|
||||
# Check if folder exists
|
||||
debug "Check if source folder \"${folder_to_backup}\" exists..."
|
||||
if [[ -d "${folder_to_backup}" ]]; then
|
||||
# Exist => continue
|
||||
info "Source folder \"${folder_to_backup}\" exists!"
|
||||
# Make sure backup destination exists
|
||||
backup_basename=$(replace_slash_with_dash "${folder_to_backup}")
|
||||
absolute_backup_destination=$(strip_duplicate_slashes_in_path "${backup_destination}/${backup_basename}")
|
||||
if [[ ! -d "${absolute_backup_destination}" ]]; then
|
||||
info "Backup destination folder \"${absolute_backup_destination}\" doesn't exist. Creating..."
|
||||
mkdir -p "${absolute_backup_destination}"
|
||||
fi
|
||||
|
||||
# Check if backup already exists (to make sure)
|
||||
if [[ -f "${absolute_backup_destination}/${timestamp}.tar.gz" ]]; then
|
||||
error "Backup \"${absolute_backup_destination}/${timestamp}.tar.gz\" already exists. Skipping..."
|
||||
else
|
||||
# Start backup
|
||||
info "Starting backup \"${absolute_backup_destination}/${timestamp}.tar.gz\""
|
||||
tar ${tar_options} -czf "${absolute_backup_destination}/${timestamp}.tar.gz" -P "${folder_to_backup}" "${tar_exclude_parameters[@]}"
|
||||
if [[ $? -eq 0 ]]; then
|
||||
success "Backup \"${absolute_backup_destination}/${timestamp}.tar.gz\" successfully completed!"
|
||||
else
|
||||
error "Backup \"${absolute_backup_destination}/${timestamp}.tar.gz\" failed..."
|
||||
fi
|
||||
fi
|
||||
|
||||
# Remove old backups
|
||||
if [[ ! -z "${backup_retention}" ]]; then
|
||||
find "${absolute_backup_destination}/" -maxdepth 1 -mtime "${backup_retention}" -type f -exec rm -rf {} \;
|
||||
fi
|
||||
else
|
||||
# Doesn't exist => skip
|
||||
error "Folder \"${folder_to_backup}\" doesn't exist. Skipping..."
|
||||
fi
|
||||
# Increment $current_task variable
|
||||
current_task=$((current_task+1))
|
||||
done
|
||||
|
||||
# Set prefix variables for pre-commands
|
||||
current_action="post-command"
|
||||
current_task=1
|
||||
total_tasks="${#post_commands[@]}"
|
||||
|
||||
# Iterate through post_commnads
|
||||
if [[ "${#post_commands[@]}" -ne 0 ]]; then
|
||||
info "Found post commands..."
|
||||
# Run each post command
|
||||
for post_command in "${post_commands[@]}"; do
|
||||
info "Running \"${post_command}\":"
|
||||
eval "${post_command}"
|
||||
# Check if post command ran successfully
|
||||
if [[ $? -eq 0 ]]; then
|
||||
success "Post command \"${post_command}\" successfully completed!"
|
||||
else
|
||||
error "Post command \"${post_command}\" failed..."
|
||||
fi
|
||||
done
|
||||
fi
|
||||
|
||||
# Return exit code
|
||||
exit 0
|
26
multibackup.conf
Normal file
26
multibackup.conf
Normal file
@ -0,0 +1,26 @@
|
||||
# Timestamp format, used in the backup target filename
|
||||
timestamp=$(date +%Y%m%d)
|
||||
|
||||
# Destination where you want to store your backups
|
||||
backup_destination="/var/backups"
|
||||
|
||||
# Folders to backup
|
||||
folders_to_backup=(
|
||||
"/var/www"
|
||||
"/var/lib/mysql"
|
||||
)
|
||||
|
||||
# Files and folders that are excluded in the tar command
|
||||
tar_excludes=()
|
||||
|
||||
# Additional tar Options
|
||||
tar_options=()
|
||||
|
||||
# How long to you want to keep your backups (in days)
|
||||
backup_retention="+7"
|
||||
|
||||
# Commands that are executed before the backup started
|
||||
pre_commands=()
|
||||
|
||||
# Commands that are executed after the backup is completed
|
||||
post_commands=()
|
Reference in New Issue
Block a user