forked from Mins/TuxLite
-
Notifications
You must be signed in to change notification settings - Fork 0
/
backup.sh
344 lines (277 loc) · 11.3 KB
/
backup.sh
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
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
#!/bin/bash
FIND_PATH="/home/*/domains/*"
# Used to filter database name from its full system path
# (1)/var(2)/lib(3)/mysql(4)/dbname(5)
AWK_DB_POS="5"
# Used to filter domain name from its full system path
# E.g. (1)/home(2)/john(3)/domains(4)/johndomain.com(5)
AWK_DOMAIN_POS="5"
source ./options.conf
function ask_interval {
# Ask user how often do they want the backup jobs to run?
echo "How often do you want the backups/cleanups to run?"
echo "1. Daily"
echo "2. Weekly"
echo "3. Monthly"
# Initialize variable with an alphabet
SELECT_INTERVAL="a"
# Keep looping until user enters a number that is greater than 0 and less than 3
until [[ "$SELECT_INTERVAL" =~ [0-9]+ ]] && [ $SELECT_INTERVAL -gt 0 ] && [ $SELECT_INTERVAL -le 3 ]; do
echo -n "Selection (integer) : "
read SELECT_INTERVAL
done
if [ $SELECT_INTERVAL -eq 1 ]; then
INTERVAL="daily"
elif [ $SELECT_INTERVAL -eq 2 ]; then
INTERVAL="weekly"
elif [ $SELECT_INTERVAL -eq 3 ]; then
INTERVAL="monthly"
fi
} # End of ask_interval
function find_available_domains {
# Initialize variable
DOMAINS_AVAILABLE=0
# First check to see if there are domains available. Suppress exit status.
find $FIND_PATH -maxdepth 0 &> /dev/null
# If exit status is 0, there are domains available
# Collect available domains to a temporary file
if [ $? -eq 0 ]; then
find $FIND_PATH -maxdepth 0 > /tmp/domain.txt
DOMAINS_AVAILABLE=`cat /tmp/domain.txt | wc -l`
# Remove fcgi-bin directory as available domain. #Not used for multiuser scripts
# sed -i '/\/srv\/www\/fcgi-bin.d/ d' /tmp/domain.txt
fi
# Exit status of find command is 1, ask user to add domain first
if [ $DOMAINS_AVAILABLE -eq 0 ]; then
echo "No domains available for backup. Please add a domain first."
exit
fi
} # End of find_available_domains
function find_available_databases {
# Initialize variable
DATABASES_AVAILABLE=0
# First search for available mysql databases
find /var/lib/mysql/* -maxdepth 0 -type d > /tmp/database.txt
# Remove mysql and phpmyadmin as available databases
sed -i '/\/var\/lib\/mysql\/mysql/ d' /tmp/database.txt
sed -i '/\/var\/lib\/mysql\/phpmyadmin/ d' /tmp/database.txt
DATABASES_AVAILABLE=`cat /tmp/database.txt | wc -l`
# No databases found, ask user to add database first
if [ $DATABASES_AVAILABLE -eq 0 ]; then
echo "No databases available for backup. Please add a database first."
exit
fi
} # End of find_available_databases
function create_backup_directory {
# First check if Linux user exists
# If yes, create backup folders
if [ -d "/home/$USER" ]; then
mkdir -p /home/$USER/backup/{databases,domains}
chown -R $USER:$USER /home/$USER/backup
echo -e "\033[35;1mBackup folders created in /home/$USER/backup.\033[0m"
else
# If not, exit and inform user
echo -e "\033[35;1mERROR: User /home/$USER doesn't exist.\033[0m"
exit 1
fi
} # End of create_backup_directory
function cron_backupdb {
# First check if backup location exists. Exit if not found.
if [ ! -d "/home/$USER/backup/databases" ]; then
echo -e "\033[35;1mERROR: Database folder /home/$USER/backup/databases doesn't exist, please create it first.\033[0m"
exit 1
fi
# Initialize selection value when listing available databases to user
counter=1
# Check how many databases are available
DB_AVAILABLE=`cat /tmp/database.txt | wc -l`
# Print out available databases
echo ""
echo "Select the database you want to backup, 1 to $DB_AVAILABLE"
while read LINE; do
# For each domain path, use AWK to get only the domain name and leave out the full path
data=`echo $LINE | awk -F"/" '{ print $'${AWK_DB_POS}' }'`
echo "$counter. $data"
# Increment counter for next iteration
let counter+=1
done < "/tmp/database.txt"
# Reduce counter by 1 for next function
let counter-=1
# Ensure that the user inputs a valid integer
# Initialize variable with a alphabet
SELECTDB="a"
# Keep on looping until input is a number that is greater than 0 and less than the number of available databases
until [[ "$SELECTDB" =~ [0-9]+ ]] && [ $SELECTDB -gt 0 ] && [ $SELECTDB -le $counter ]; do
echo -n "Selection (integer) : "
read SELECTDB
done
# Capture database name from its full path using AWK
DATABASE=`cat /tmp/database.txt | awk NR==$SELECTDB | awk -F"/" '{ print $'${AWK_DB_POS}' }'`
# Remove temporary file
rm -rf /tmp/database.txt
# Check to see if database is already backed up under cronjobs
# First dump cron contents to temporary file
crontab -l > /tmp/tmpcron.txt
# Then search for existing string
tmp=`grep -w "@$INTERVAL mysqldump -hlocalhost -uroot -p$MYSQL_ROOT_PASSWORD $DATABASE" /tmp/tmpcron.txt | wc -l`
command rm /tmp/tmpcron.txt
# If cron entry already exists, abort
if [ $tmp -gt 0 ]; then
echo -e "\033[35;1mERROR: Database backup already exists, please remove it from crontab -e before entering again.\033[0m"
exit 1
fi
# If not, then append a cronjob for it
crontab -l > /tmp/tmpcron.txt
cat >> /tmp/tmpcron.txt <<EOF
@$INTERVAL mysqldump -hlocalhost -uroot -p$MYSQL_ROOT_PASSWORD $DATABASE | gzip -9 > /home/$USER/backup/databases/$DATABASE.\`/bin/date +\%Y\%m\%d\`.sql.gz; chown $USER:$USER /home/$USER/backup/databases/*
EOF
# Load job commands back to crontab
crontab /tmp/tmpcron.txt
# Remove temporary file
command rm /tmp/tmpcron.txt
echo -e "\033[35;1mDatabase $DATABASE will be backed up to /home/$USER/backup/databases/$DATABASE $INTERVAL.\033[0m"
echo -e "\033[35;1mTo verify, enter crontab -e.\033[0m"
} # End of cron_backupdb
function cron_backupdomain {
# First check if backup location exists. Exit if not found.
if [ ! -d "/home/$USER/backup/domains" ]; then
echo -e "\033[35;1mERROR: Backup folder /home/$USER/backup/domains doesn't exist, please create it first.\033[0m"
exit 1
fi
# Print out available domains and
# Ensure that the user inputs a valid integer
# Initialize counter
counter=1
DOMAINS_AVAILABLE=`cat /tmp/domain.txt | wc -l`
echo ""
echo "Select the domain you want to backup, 1 to $DOMAINS_AVAILABLE"
# Print out domains. Use AWK to filter out domain name from full paths
while read LINE; do
data=`echo $LINE | awk -F"/" '{ print $'${AWK_DOMAIN_POS}' }'`
echo "$counter. $data"
let counter+=1
done < "/tmp/domain.txt"
# Set counter for next function
let counter-=1
# Ensure that the user inputs a valid integer
# Initialize variable with a alphabet
SELECTDOMAIN="a"
# Keep on looping until input is a number that is greater than 0 and less than the number of available databases
until [[ "$SELECTDOMAIN" =~ [0-9]+ ]] && [ $SELECTDOMAIN -gt 0 ] && [ $SELECTDOMAIN -le $counter ]; do
echo -n "Selection (integer) : "
read SELECTDOMAIN
done
# Get full path to domain e.g /home/user/domains/domain.com
DOMAIN=`cat /tmp/domain.txt | awk NR==$SELECTDOMAIN`
# Remove first forward slash so that tar doesn't output anything during backup
DOMAIN=`echo $DOMAIN | cut -c2-`
# Get domain name without its system path. Used for naming the backup file
DOMAIN_URL=`cat /tmp/domain.txt | awk NR==$SELECTDOMAIN | awk -F"/" '{ print $'${AWK_DOMAIN_POS}' }'`
rm -rf /tmp/domain.txt
# Check to see if cronjob already exists
# Load crontab contents into temporary file and grep the domain name
crontab -l > /tmp/tmpcron.txt
tmp=`grep -w "$DOMAIN" /tmp/tmpcron.txt | wc -l`
command rm /tmp/tmpcron.txt
# If cron entry already exists then exit
if [ $tmp -gt 0 ]; then
echo -e "\033[35;1mERROR: Domain backup cronjob already exists, please remove it from crontab -e before trying again.\033[0m"
exit 1
fi
# Dump out contents of crontab, and add new line to it
crontab -l > /tmp/tmpcron.txt
cat >> /tmp/tmpcron.txt <<EOF
@$INTERVAL tar -czf /home/$USER/backup/domains/$DOMAIN_URL.\`/bin/date +\%Y\%m\%d\`.tar.gz -C / $DOMAIN; chown $USER:$USER /home/$USER/backup/domains/*
EOF
# Restore cron contents from temporary file
crontab /tmp/tmpcron.txt
# Remove temporary file
command rm /tmp/tmpcron.txt
echo -e "\033[35;1mDomain $DOMAIN_URL will be backed up to /home/$USER/backup/domains/$DOMAIN_URL $INTERVAL.\033[0m"
echo -e "\033[35;1mTo verify, enter crontab -e.\033[0m"
} # End of cron_backupdomain
function cron_cleanbackup {
if [ ! -d "/home/$USER" ]; then
echo -e "\033[35;1mERROR: Folder /home/$USER/backup doesn't exist, please enter a valid system user.\033[0m"
return 1
fi
if ! [[ "$DAYS" =~ ^[0-9]+$ ]]; then
echo -e "\033[35;1mERROR: Please enter a valid \"Old\" integer.\033[0m"
return 1
fi
# Dump out contents of crontab, and add new line to it
crontab -l > /tmp/tmpcron.txt
cat >> /tmp/tmpcron.txt <<EOF
@$INTERVAL find /home/$USER/backup/* -type f -mtime +$DAYS -exec rm -rfv {} \; > /home/$USER/cleanbackup.log; chown $USER:$USER /home/$USER/cleanbackup.log
EOF
crontab /tmp/tmpcron.txt
command rm /tmp/tmpcron.txt
echo -e "\033[35;1mBackup files older than $DAYS days will be removed from /home/$USER/backup.\033[0m"
echo -e "\033[35;1mTo verify, enter crontab -e.\033[0m"
}
# Start main program
if [ ! -n "$1" ]; then
echo ""
echo -n "$0"
echo -ne "\033[36m dir User\033[0m"
echo " - Create backup /home/User/backup/{domains,databases} directories to store backup files from cronjob."
echo -n "$0"
echo -ne "\033[36m db User\033[0m"
echo " - Set up cronjob to mysqldump a database to USER's backup directory."
echo -n "$0"
echo -ne "\033[36m site User\033[0m"
echo " - Set up cronjob to tar.gz a domain's public_html to User's backup directory."
echo -n "$0"
echo -ne "\033[36m cleanup Old User\033[0m"
echo " - Set up cronjob to remove backups files that are older than \"Old\"(integer) days from User's backup directory."
echo ""
exit
fi
case $1 in
dir)
# Make sure user inputs all the backup command and the user
if [ ! $# -eq 2 ]; then
echo -e "\033[35;1mPlease enter all required parameters\033[0m"
exit 1
else
USER=$2
create_backup_directory
fi
;;
db)
# Make sure user inputs all the backup command and the user
if [ ! $# -eq 2 ]; then
echo -e "\033[35;1mPlease enter all required parameters\033[0m"
exit 1
else
USER=$2
find_available_databases
ask_interval
cron_backupdb
fi
;;
site)
# Make sure user inputs all the backup command and the user
if [ ! $# -eq 2 ]; then
echo -e "\033[35;1mPlease enter all required parameters\033[0m"
exit 1
else
USER=$2
find_available_domains
ask_interval
cron_backupdomain
fi
;;
cleanup)
# Make sure user inputs all the backup command, the user and the days params
if [ ! $# -eq 3 ]; then
echo -e "\033[35;1mPlease enter all required parameters\033[0m"
exit 1
else
USER=$3
DAYS=$2
ask_interval
cron_cleanbackup
fi
;;
esac