forked from frdmn/tar-multibackup
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathmultibackup
executable file
·208 lines (180 loc) · 5.78 KB
/
multibackup
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
#!/usr/bin/env bash
[[ -n "${DEBUG}" ]] && set -x
###
# Configuration
###
# Use "~/.multibackup" as default config, if $CONFIG is not specified
CONFIG="${CONFIG:-${HOME}/.multibackup}"
###
# Functions
###
# Color helpers
color_red=$(tput setaf 1)
color_yellow=$(tput setaf 3)
color_green=$(tput setaf 2)
color_reset=$(tput sgr0)
# Extension
ext=".tar.gz"
# 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-list
current_action="backup-list"
current_task=1
total_tasks="${#files_to_backup[@]}"
backup_list=()
# Iterate through "$files_to_backup"
for file_to_backup in "${files_to_backup[@]}"; do
# Set name source type
type="Folder"
if [[ -f "${file_to_backup}" ]]; then
type="File"
fi
# Check if folder/file exists
debug "Check if source ${type} \"${file_to_backup}\" exists..."
if [[ -d "${file_to_backup}" ]] || [[ -f "${file_to_backup}" ]]; then
# Exist => continue
info "Source ${type} \"${file_to_backup}\" exists!"
# Make sure backup destination exists
backup_basename=$(replace_slash_with_dash "${file_to_backup}")
backup_list+=( "-P ${file_to_backup}" )
else
# Doesn't exist => skip
error "${type} \"${file_to_backup}\" doesn't exist. Skipping..."
fi
# Increment $current_task variable
current_task=$((current_task+1))
done
# Set prefix variables for backup
current_action="backup"
current_task=1
total_tasks=1
absolute_backup_destination=$(strip_duplicate_slashes_in_path "${backup_destination}")
if [[ ! -d "${absolute_backup_destination}" ]]; then
info "Backup destination folder \"${absolute_backup_destination}\" doesn't exist. Creating..."
mkdir -p "${absolute_backup_destination}"
fi
if [[ -n "${ENCRYPT}" ]]; then
ext=".tar.gz.enc"
fi
# Check if backup already exists (to make sure)
if [[ -f "${absolute_backup_destination}/${timestamp}${ext}" ]]; then
error "Backup \"${absolute_backup_destination}/${timestamp}${ext}\" already exists. Skipping..."
else
# Start backup
info "Starting backup \"${absolute_backup_destination}/${timestamp}.tar.gz\""
tar czf "${absolute_backup_destination}/${timestamp}.tar.gz" "${tar_exclude_parameters[@]}" ${backup_list[@]}
if [[ -n "${ENCRYPT}" ]]; then
info "Starting encrypt \"${absolute_backup_destination}/${timestamp}.tar.gz\""
openssl enc -in "${absolute_backup_destination}/${timestamp}.tar.gz" -aes-256-cbc -pass env:ENCRYPT -out "${absolute_backup_destination}/${timestamp}${ext}"
if [[ $? -eq 0 ]]; then
info "Remove \"${absolute_backup_destination}/${timestamp}.tar.gz\""
rm -rf "${absolute_backup_destination}/${timestamp}.tar.gz"
ext=".tar.gz.enc"
fi
fi
chmod 600 "${absolute_backup_destination}/${timestamp}${ext}"
if [[ $? -eq 0 ]]; then
success "Backup \"${absolute_backup_destination}/${timestamp}${ext}\" successfully completed!"
else
error "Backup \"${absolute_backup_destination}/${timestamp}${ext}\" 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
# 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