First Commit

This commit is contained in:
Patrick Niebeling
2024-11-19 11:42:07 +01:00
commit 303c790d99
4 changed files with 314 additions and 0 deletions

21
LICENSE Normal file
View 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
View 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
View 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
View 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=()