-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathext-backup
executable file
·131 lines (117 loc) · 3.29 KB
/
ext-backup
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
#!/usr/bin/env bash
# back up /{etc,home,var} to a LUKS encrypted external drive
# TODO: add options for progress bar, no output and verbose (current)
# TODO: make include and exclude patterns as variables
# TODO: allow these to be passed as arguments
includeFile="${HOME}/bin/.rInclude"
excludeFile="${HOME}/bin/.rExclude"
cryptDevice="external"
externalDrive="/dev/sdc"
mountPoint="/mnt"
logLocation="/tmp/ext-backup_$(date '+%s').log"
USER_HOME="$(getent passwd "${SUDO_USER}" | cut -d':' -f6)"
check_disk() {
# TODO: this section is finicky, make sure it responds properly
if lsblk -l | grep "/dev/mapper/${cryptDevice}" >/dev/null; then
cryptsetup open "${externalDrive}" "${cryptDevice}"
printf -- '%s\n' "'${externalDrive}' opened as '${cryptDevice}'"
else
printf -- '%s\n' "'${externalDrive}' already open as '${cryptDevice}'"
fi
if ! df | awk '{print $6}' | grep "${mountPoint}" >/dev/null; then
mount "/dev/mapper/${cryptDevice}" "${mountPoint}"
printf -- '%s\n' "'${cryptDevice}' mounted to ${mountPoint}"
elif [[ "$(df '/mnt' | awk 'NR==2 {print $1}')" == "/dev/mapper/${cryptDevice}" ]]; then
printf -- '%s\n' "'${cryptDevice}' already mounted to '${mountPoint}'"
else
unmount_close "'${mountPoint}' in use by another device"
exit 1
fi
printf -- '%s\n%s\n' "Disk successfully decrypted and mounted." "Ready for backup."
return 0
}
check_root() {
# exit if user is not root
if (("$(id -u)" != 0)); then
print_errors "Run as root." "Cancelling operation."
exit 1
fi
}
sync_main() {
# sync user's "/home" and then "/var" and "/etc"
# if you want to add another dir, just provide it as an arg to sync_dirs
# TODO: make verbosity an option
if ! rsync -acmuz \
--info=progress2 \
--exclude-from="${excludeFile}" \
--include-from="${includeFile}" \
--delay-updates \
--delete-delay \
--delete-excluded \
--ignore-existing \
--log-file="${logLocation}" \
"${USER_HOME}" "${mountPoint}"; then
unmount_close "Syncing '${USER_HOME}' failed"
exit 4
else
printf -- '%s\n' "'/home' successfully synced"
fi
if ! sync_dirs "/etc" "/var"; then
unmount_close "Syncing '/etc' and/or '/var' failed"
exit 4
else
printf -- '%s\n' "'/etc' and '/var' successfully synced"
fi
return 0
}
sync_dirs() {
# run through all given directories to copy them, ignoring temp files
while (("$#")); do
rsync -mapy \
--exclude='*.cache' \
--exclude='*cache/' \
--exclude='*.tmp' \
--exclude='*tmp/' \
--info=progress2 \
--delay-updates \
--delete-delay \
--delete-excluded \
--ignore-existing \
--log-file="${logLocation}" \
"$1" "${mountPoint}"
shift
done
return 0
}
print_errors() {
tput setaf 1
printf -- '[ERR] %s\n' "$*" >&2
tput sgr0
}
unmount_close() {
# unmount the external drive and close the LUKS container
if (($# == 1)); then
print_errors "Error: $1!"
read -rp "Unmount and close disk? [Y/n] " closeDisk
case "$closeDisk" in
y | Y)
:
;;
*)
printf -- '%s\n' "Leaving '${externalDrive}' decrypted and mounted."
exit 2
;;
esac
fi
umount "${mountPoint}"
cryptsetup close "${cryptDevice}"
return 0
}
main() {
check_root
check_disk
sync_main
unmount_close
}
main
exit 0