~m-grant-prg/lixbackups/trunk

« back to all changes in this revision

Viewing changes to source/progs/bash/netbckup.sh.in

  • Committer: Mark Grant
  • Date: 2017-05-01 09:22:42 UTC
  • mto: This revision was merged to the branch mainline in revision 12.
  • Revision ID: m.grant.prg@gmail.com-20170501092242-7wfdrcutul5h2kty
Tags: upstream-1.2.5-12-g20783e6
ImportĀ upstreamĀ versionĀ 1.2.5-12-g20783e6

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
#! /usr/bin/env bash
 
2
#########################################################################
 
3
#                                                                       #
 
4
#       netbckup is automatically generated,                            #
 
5
#               please do not modify!                                   #
 
6
#                                                                       #
 
7
#########################################################################
 
8
 
 
9
#########################################################################
 
10
#                                                                       #
 
11
# Script ID: netbckup                                                   #
 
12
# Author: Mark Grant                                                    #
 
13
#                                                                       #
 
14
# Purpose:                                                              #
 
15
# Depending on command line arguments runs:-                            #
 
16
#       a full ad hoc backup.                                           #
 
17
#       a level 0 --listed-incremental (ie full) backup of entire file  #
 
18
#               system. It allows for a cycle of 5 backups for weekly   #
 
19
#               coverage, designated by 1 - 5.                          #
 
20
#       a level 1 --listed-incremental backup to produce a differential #
 
21
#               backup.                                                 #
 
22
#       a level 1 - n --listed-incremental backup to produce an         #
 
23
#               incremental backup.                                     #
 
24
#       a selective backup.                                             #
 
25
#                                                                       #
 
26
# Syntax:      netbckup [ -d or --differential || -f or --full ||       #
 
27
#                       -h or --help || -i or --incremental ||          #
 
28
#                       -s or --selective || -V or --version ||         #
 
29
#                       -w or --weekly ]                                #
 
30
#                                                                       #
 
31
# Exit Codes:   0 & 64 - 113 as per C/C++ standard                      #
 
32
#               0 - success                                             #
 
33
#               64 - Invalid arguments                                  #
 
34
#               65 - Failed mounting backup network share               #
 
35
#               66 - backup.snar non-existent or inaccesssible          #
 
36
#               67 - trap received                                      #
 
37
#                                                                       #
 
38
#########################################################################
 
39
 
 
40
#########################################################################
 
41
#                                                                       #
 
42
# Changelog                                                             #
 
43
#                                                                       #
 
44
# Date          Author  Version Description                             #
 
45
#                                                                       #
 
46
# 24/09/2014    MG      1.0.1   Created from consolidation of seperate  #
 
47
#                               full, weekly, daily and data scripts.   #
 
48
# 28/09/2014    MG      1.0.2   Changed latency_compensate function to  #
 
49
#                               attempt 1 execution of command without  #
 
50
#                               causing a sleep.                        #
 
51
# 30/09/2014    MG      1.0.3   If the root account is accessible, ('P' #
 
52
#                               from passwd -S), then deny login access #
 
53
#                               to non-root users for the duration of   #
 
54
#                               the backup. If root is not accessible,  #
 
55
#                               then do not deny access as it would be  #
 
56
#                               dangerous if for some reason it is not  #
 
57
#                               re-allowed. Only root would have access.#
 
58
#                               (Even though shutdown clears the        #
 
59
#                               restriction, this script does not       #
 
60
#                               demand a shutdown).                     #
 
61
# 22/11/2014    MG      1.0.4   Add overall package version to -V.      #
 
62
# 22/11/2014    MG      1.0.5   Switched from getopts to GNU getopt to  #
 
63
#                               allow long options.                     #
 
64
# 03/02/2015    MG      1.0.6   Remove BSD support.                     #
 
65
# 03/02/2015    MG      1.2.1   Add support for NFS backup shares. Add  #
 
66
#                               support for different backup share      #
 
67
#                               targets for weekly and ad hoc type      #
 
68
#                               backups. Remove latency_compensate      #
 
69
#                               function as improved hardware or        #
 
70
#                               removal of BSD has cured the problem.   #
 
71
# 24/02/2015    MG      1.2.2   Change configuration files directory to #
 
72
#                               lixbackups to limit risk of conflict    #
 
73
#                               with other backup packages.             #
 
74
# 26/02/2015    MG      1.2.3   Use logger to write key messages to     #
 
75
#                               syslog.                                 #
 
76
# 01/03/2015    MG      1.2.4   Use log file in localstatedir/log. Log  #
 
77
#                               file management set to use logrotate in #
 
78
#                               this package release.                   #
 
79
# 16/03/2015    MG      1.2.5   Improve logging.                        #
 
80
# 05/06/2015    MG      1.2.6   Reduce df output from df -ah to a more  #
 
81
#                               sensible df -h.                         #
 
82
#                                                                       #
 
83
#########################################################################
 
84
 
 
85
##################
 
86
# Init variables #
 
87
##################
 
88
script_exit_code=0
 
89
version="1.2.6"                         # set version variable
 
90
etclocation=@sysconfdir@/lixbackups     # Path to etc directory
 
91
outputprefix="netbckup: "
 
92
differential=FALSE
 
93
fulladhoc=FALSE
 
94
incremental=FALSE
 
95
selective=FALSE
 
96
weekly=FALSE
 
97
bckuptype=""                            # Selected backup type
 
98
bckupCL=""                              # Backup command line
 
99
packageversion=@pkgversion@             # Version of the complete package
 
100
weeklynotifyuser=""
 
101
adhocnotifyuser=""
 
102
notifyuser=""
 
103
attachtype=""                           # attbckshare  weekly or adhoc
 
104
loglocation=@localstatedir@/log         # Log file location
 
105
 
 
106
#############
 
107
# Functions #
 
108
#############
 
109
 
 
110
# Output $1 to stdout or stderr depending on $2 and write to syslog if required.
 
111
# Syntax = output $1 (The message) $2 (0 = stdout, > 0 = stderr) $3 (TRUE = syslog it).
 
112
output()
 
113
{
 
114
        if [ $2 = 0 ]
 
115
        then
 
116
                echo $(date +'[ %a %b %d %T ]')" $outputprefix$1"
 
117
        else
 
118
                echo $(date +'[ %a %b %d %T ]')" $outputprefix$1" 1>&2
 
119
        fi
 
120
        if [ $3 = TRUE ]
 
121
        then
 
122
                logger "$outputprefix$1"
 
123
                std_cmd_err_handler $?
 
124
        fi
 
125
}
 
126
 
 
127
# Standard function to test command error ($1 is $?) and exit if non-zero
 
128
std_cmd_err_handler()
 
129
{
 
130
        if [ $1 != 0 ]
 
131
        then
 
132
                script_exit_code=$1
 
133
                script_exit
 
134
        fi
 
135
}
 
136
 
 
137
# Standard function to cleanup and return exit code
 
138
script_exit()
 
139
{
 
140
# The backup share might or might not be mounted.
 
141
if [ "$(chkbckshare -bt)" = "TRUE" ]
 
142
then
 
143
        detbckshare
 
144
        # No error check cos could loop via std_cmd_err_handler
 
145
fi
 
146
 
 
147
# FD's 6 & 7 may or may not be open at this point so test individually for closing.
 
148
# This reads lsof with ANDed conditions of suppress warnings, FD 6, output only FD
 
149
# for this current PID and pipe it's output to wc to count the lines. If FD 6 is
 
150
# open, 2 lines result, PID number and f6.
 
151
if [ $(lsof -aw -d 6 -F f -p $$ | wc -l) -gt 0 ]
 
152
then
 
153
        # Final log entries and restore stdout & stderr
 
154
        output $script_short_desc" completed with status $script_exit_code" $script_exit_code FALSE
 
155
        output "Processing of "$backpath" is complete. Status: $script_exit_code" $script_exit_code FALSE
 
156
 
 
157
        exec 1>&6 6>&-  # Restore stdout and close FD 6
 
158
fi
 
159
if [ $(lsof -aw -d 7 -F f -p $$ | wc -l) -gt 0 ]
 
160
then
 
161
        exec 2>&7 7>&-  # Restore stderr and close FD 7
 
162
fi
 
163
 
 
164
# Re-Allow logins
 
165
rm -f /etc/nologin
 
166
 
 
167
output $script_short_desc" completed with status "$script_exit_code $script_exit_code TRUE
 
168
 
 
169
exit $script_exit_code
 
170
}
 
171
 
 
172
# Standard trap exit function
 
173
trap_exit()
 
174
{
 
175
script_exit_code=67
 
176
output "Script terminating due to trap received." 1 TRUE
 
177
script_exit
 
178
}
 
179
 
 
180
# Setup trap
 
181
trap trap_exit SIGHUP SIGINT SIGTERM
 
182
 
 
183
########
 
184
# Main #
 
185
########
 
186
# Process command line arguments with GNU getopt.
 
187
GETOPTTEMP=`getopt -o dfhisVw \
 
188
                --long differential,full,help,incremental,selective,version,weekly -n "$0" -- "$@"`
 
189
status=$?
 
190
if [ $status != 0 ]
 
191
then
 
192
        exit $status
 
193
fi
 
194
 
 
195
eval set -- "$GETOPTTEMP"
 
196
status=$?
 
197
if [ $status != 0 ]
 
198
then
 
199
        exit $status
 
200
fi
 
201
 
 
202
while true
 
203
do
 
204
        case "$1" in
 
205
        -d|--differential)
 
206
                if [ $fulladhoc = TRUE -o $incremental = TRUE -o $selective = TRUE -o $weekly = TRUE ]
 
207
                then
 
208
                        output "Options d, f, i, s and w are all mutually exclusive." 64 FALSE
 
209
                        exit 64
 
210
                fi
 
211
                differential=TRUE
 
212
                bckuptype="differential"
 
213
                attachtype="weekly"
 
214
                script_short_desc=$(uname -n)" "$(date +%A)" Daily Differential Backup"
 
215
                shift
 
216
                ;;
 
217
        -f|--full)
 
218
                if [ $differential = TRUE -o $incremental = TRUE -o $selective = TRUE -o $weekly = TRUE ]
 
219
                then
 
220
                        output "Options f, i, s, w and d are all mutually exclusive." 64 FALSE
 
221
                        exit 64
 
222
                fi
 
223
                fulladhoc=TRUE
 
224
                bckuptype="fulladhoc"
 
225
                attachtype="adhoc"
 
226
                script_short_desc=$(uname -n)" Ad Hoc Full Backup "$(date '+%Y%m%d%H%M')
 
227
                shift
 
228
                ;;
 
229
        -h|--help)
 
230
                echo "Usage is $0 [options]"
 
231
                echo "  -d or --differential - perform a differential backup"
 
232
                echo "  -f or --full - perform a full ad hoc backup"
 
233
                echo "  -h or --help displays usage information"
 
234
                echo "  -i or --incremental - perform an incremental backup"
 
235
                echo "  -s or --selective - perform a selective backup"
 
236
                echo "  -V or --version displays version information"
 
237
                echo "  OR"
 
238
                echo "  -w or --weekly - perform a weekly full backup"
 
239
                shift
 
240
                exit 0
 
241
                ;;
 
242
        -i|--incremental)
 
243
                if [ $fulladhoc = TRUE -o $differential = TRUE -o $selective = TRUE -o $weekly = TRUE ]
 
244
                then
 
245
                        output "Options i, s, w, d and f are all mutually exclusive." 64 FALSE
 
246
                        exit 64
 
247
                fi
 
248
                incremental=TRUE
 
249
                bckuptype="incremental"
 
250
                attachtype="weekly"
 
251
                script_short_desc=$(uname -n)" "$(date +%A)" Daily Incremental Backup"
 
252
                shift
 
253
                ;;
 
254
        -s|--selective)
 
255
                if [ $fulladhoc = TRUE -o $differential = TRUE -o $incremental = TRUE -o $weekly = TRUE ]
 
256
                then
 
257
                        output "Options s, w, d, f and i are all mutually exclusive." 64 FALSE
 
258
                        exit 64
 
259
                fi
 
260
                selective=TRUE
 
261
                bckuptype="selective"
 
262
                attachtype="adhoc"
 
263
                script_short_desc=$(uname -n)" "$(date +%A)" Selective Backup"
 
264
                shift
 
265
                ;;
 
266
        -V|--version)   echo "$0 Script version "$version
 
267
                echo "$0 Package version "$packageversion
 
268
                shift
 
269
                exit 0
 
270
                ;;
 
271
        -w|--weekly)
 
272
                if [ $fulladhoc = TRUE -o $differential = TRUE -o $incremental = TRUE -o $selective = TRUE ]
 
273
                then
 
274
                        output "Options w, d, f, i and s are all mutually exclusive." 64 FALSE
 
275
                        exit 64
 
276
                fi
 
277
                weekly=TRUE
 
278
                bckuptype="weekly"
 
279
                attachtype="weekly"
 
280
                # Calculate backup sequence number.
 
281
                # Remove leading zeros otherwise thinks it is octal
 
282
                day=$(date +%d)
 
283
                day=$(echo $day | sed 's/^0*//')
 
284
                bckseq=1
 
285
                if [ $day -gt 28 ]; then
 
286
                        bckseq=5
 
287
                        elif [ $day -gt 21 ] ; then
 
288
                                bckseq=4
 
289
                                elif [ $day -gt 14 ] ; then
 
290
                                        bckseq=3
 
291
                                        elif [ $day -gt 7 ] ; then
 
292
                                                bckseq=2
 
293
                fi
 
294
                script_short_desc=$(uname -n)" Weekly Full Backup - "$bckseq
 
295
                shift
 
296
                ;;
 
297
        --)     shift
 
298
                break
 
299
                ;;
 
300
        *)      output "Internal error." 1 FALSE
 
301
                exit 1
 
302
                ;;
 
303
        esac
 
304
done
 
305
 
 
306
# Script does not accept other arguments.
 
307
if [ $# -gt 0 ]
 
308
then
 
309
        output "Invalid argument." 64 FALSE
 
310
        exit 64
 
311
fi
 
312
 
 
313
# One option has to be selected.
 
314
if [ $differential = FALSE -a $fulladhoc = FALSE -a $incremental = FALSE \
 
315
        -a $selective = FALSE -a $weekly = FALSE ]
 
316
then
 
317
        output "Either d, f, i, s or w must be set." 64 FALSE
 
318
        exit 64
 
319
fi
 
320
 
 
321
output "Refer to $loglocation/lixbackups.log for further information." 0 TRUE
 
322
output "$script_short_desc" 0 TRUE
 
323
 
 
324
# Ensure backup log exists.
 
325
mkdir -p $loglocation
 
326
if [ ! -f $loglocation/lixbackups.log ]
 
327
then
 
328
        touch $loglocation/lixbackups.log
 
329
        std_cmd_err_handler $?
 
330
        chown syslog:adm $loglocation/lixbackups.log
 
331
        std_cmd_err_handler $?
 
332
        chmod 0640 $loglocation/lixbackups.log
 
333
        std_cmd_err_handler $?
 
334
fi
 
335
 
 
336
# Make copies of stdout & stderr then re-direct stdout & stderr to backup log
 
337
# and write initial entries
 
338
exec 6>&1 7>&2
 
339
 
 
340
exec 1>> $loglocation/lixbackups.log 2>&1
 
341
 
 
342
output "$script_short_desc" 0 FALSE
 
343
 
 
344
# Check to see if root account is accessible, if so, prohibit non-root login
 
345
pwdstatus=$(passwd -Sa | awk '{ if ($1 == "root")
 
346
                print $2 ;}')
 
347
 
 
348
if [ $pwdstatus = "P" ]
 
349
then
 
350
        output "Root password status is "$pwdstatus". Denying non-root login access." 0 TRUE
 
351
        echo "Login refused. Backup in progress." > /etc/nologin
 
352
else
 
353
        output "Root password status is "$pwdstatus". Login access not being denied." 0 TRUE
 
354
fi
 
355
 
 
356
# Read parameters from $etclocation/backups.conf
 
357
IFS="="
 
358
 
 
359
exec 3<$etclocation/backups.conf
 
360
while read -u3 -ra input
 
361
do
 
362
        case ${input[0]} in
 
363
        mntdir)
 
364
                mntdir=${input[1]}
 
365
                ;;
 
366
        weeklynotifyuser)
 
367
                weeklynotifyuser=${input[1]}
 
368
                ;;
 
369
        adhocnotifyuser)
 
370
                adhocnotifyuser=${input[1]}
 
371
                ;;
 
372
        esac
 
373
done
 
374
exec 3<&-
 
375
 
 
376
if [ $attachtype = "weekly" ]
 
377
then
 
378
        notifyuser=$weeklynotifyuser
 
379
else
 
380
        notifyuser=$adhocnotifyuser
 
381
fi
 
382
 
 
383
# Check to see if the network backup share is mounted, if so umount as it could
 
384
# be mounted using different parameters, then mount
 
385
if [ "$(chkbckshare -bt)" = "TRUE" ]
 
386
then
 
387
        detbckshare
 
388
        std_cmd_err_handler $?
 
389
fi
 
390
attbckshare --$attachtype --verbose
 
391
std_cmd_err_handler $?
 
392
 
 
393
# Start build of backup command
 
394
bckupCL="tar cpzf "
 
395
 
 
396
case $bckuptype in
 
397
differential)
 
398
        # Build the backup & incremental file names and paths
 
399
        backpath="$mntdir/backup"$(date +%a)".tar.gz"
 
400
        snarpath="$mntdir/backup"$(date +%a)".snar"
 
401
 
 
402
        # If the incremental files exists, delete.
 
403
        # (Just in case full backup has not done this)
 
404
        if [ -f $snarpath ] ; then
 
405
                rm $snarpath
 
406
                std_cmd_err_handler $?
 
407
        fi
 
408
 
 
409
        # Copy level 0 incremental file in order to perform a
 
410
        # level 1, effective differential backup each run.
 
411
        if [ -f $mntdir/backup.snar -a -r $mntdir/backup.snar \
 
412
                -a -w $mntdir/backup.snar ] ; then
 
413
                cp $mntdir/backup.snar $snarpath
 
414
                std_cmd_err_handler $?
 
415
        else
 
416
                script_exit_code=66
 
417
                output "backup.snar does not exist or is not accessible. Exit code "$script_exit_code 1 TRUE
 
418
                script_exit
 
419
        fi
 
420
 
 
421
        bckupCL=$bckupCL"$backpath --listed-incremental=$snarpath "
 
422
        bckupCL=$bckupCL"--exclude-from=$etclocation/bckdaily.exclude "
 
423
        ;;
 
424
fulladhoc)
 
425
        # Build the backup file name and path
 
426
        backpath="$mntdir/backup"$(date '+%Y%m%d%H%M')".tar.gz"
 
427
 
 
428
        bckupCL=$bckupCL"$backpath "
 
429
        ;;
 
430
incremental)
 
431
        # Build the backup & incremental file names and paths
 
432
        backpath="$mntdir/backup"$(date +%a)".tar.gz"
 
433
        snarpath="$mntdir/backup.snar"
 
434
 
 
435
        # Check that the incremental file exists.
 
436
        if [ ! -f $snarpath -o ! -r $snarpath -o ! -w $snarpath ] ; then
 
437
                script_exit_code=66
 
438
                output $snarpath" does not exist or is not accessible. Exit code "$script_exit_code 1 TRUE
 
439
                script_exit
 
440
        fi
 
441
 
 
442
        bckupCL=$bckupCL"$backpath --listed-incremental=$snarpath "
 
443
        bckupCL=$bckupCL"--exclude-from=$etclocation/bckdaily.exclude "
 
444
        ;;
 
445
selective)
 
446
        # Build the backup file name and path
 
447
        backpath="$mntdir/backupsel"$(date +%a)".tar.gz"
 
448
 
 
449
        bckupCL=$bckupCL"$backpath --files-from=$etclocation/bckseldaily.files "
 
450
        bckupCL=$bckupCL"--exclude-from=$etclocation/bckseldaily.exclude "
 
451
        ;;
 
452
weekly)
 
453
        # Build the backup & incremental file names and paths
 
454
        backpath="$mntdir/backup"$bckseq".tar.gz"
 
455
        snarpath="$mntdir/backup.snar"
 
456
 
 
457
        # If the level 0 incremental file exists, delete
 
458
        if [ -f $snarpath ]
 
459
        then
 
460
                rm $snarpath
 
461
                std_cmd_err_handler $?
 
462
        fi
 
463
 
 
464
        bckupCL=$bckupCL"$backpath --listed-incremental=$snarpath "
 
465
        bckupCL=$bckupCL"--exclude-from=$etclocation/bckweekly.exclude "
 
466
        ;;
 
467
esac
 
468
 
 
469
# If the backup file exists, delete
 
470
if [ -f $backpath ]
 
471
then
 
472
        rm $backpath
 
473
        std_cmd_err_handler $?
 
474
fi
 
475
 
 
476
output "Attempting to process backup - "$backpath 0 TRUE
 
477
 
 
478
# Empty the network trashbox if it exists
 
479
rm -fr $mntdir/trashbox/*
 
480
std_cmd_err_handler $?
 
481
 
 
482
# Produce list of sockets to exclude
 
483
# ignoring directories appearing in bcksystem.exclude
 
484
# If the directory being excluded is explicit then use wholename option so
 
485
# the path has to be an exact match.
 
486
# If the directory is quoted then use -name which matches any part of the full path.
 
487
 
 
488
findCL="find / -type d '(' "
 
489
count=0
 
490
exec 3<$etclocation/bcksystem.exclude
 
491
while read -u3 -ra input
 
492
do
 
493
        if [ $count != 0 ] ; then
 
494
                findCL=$findCL" -o "
 
495
        fi
 
496
        nameoption=$(echo $input | awk '{if (substr($0,1,1)=="'"'"'")
 
497
                                print "-name "
 
498
                                else
 
499
                                print "-wholename ";}')
 
500
        findCL=$findCL$nameoption$input
 
501
        ((count = count + 1))
 
502
done
 
503
exec 3<&-
 
504
 
 
505
findCL=$findCL" ')' -prune -o -type s -print > "$mntdir/sockets.exclude
 
506
 
 
507
output "Find command used:- $findCL" 0 FALSE
 
508
 
 
509
eval "$findCL"
 
510
 
 
511
# Run the backup excluding system directories
 
512
bckupCL=$bckupCL"--exclude-from=$etclocation/bcksystem.exclude "
 
513
bckupCL=$bckupCL"--exclude-from=$mntdir/sockets.exclude "
 
514
 
 
515
# If selective backup then uses --files-from so doesn't need starting node (root)
 
516
if [ $selective = TRUE ] ; then
 
517
        bckupCL=$bckupCL"--exclude-caches"
 
518
else
 
519
        bckupCL=$bckupCL"--exclude-caches /"
 
520
fi
 
521
 
 
522
output "Backup command used:- $bckupCL" 0 FALSE
 
523
eval "$bckupCL"
 
524
std_cmd_err_handler $?
 
525
 
 
526
# Mail disk stats
 
527
df -h | mailx -s "$script_short_desc" $notifyuser
 
528
 
 
529
# Mail backup file date hierarchy
 
530
ls -lht $mntdir | mailx -s "$script_short_desc" $notifyuser
 
531
 
 
532
# And exit.
 
533
script_exit_code=0
 
534
script_exit