-
Notifications
You must be signed in to change notification settings - Fork 0
/
main.sh
executable file
·194 lines (166 loc) · 4.81 KB
/
main.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
#!/usr/bin/env bash
set -e
echo "Welcome to Backup-Real-Matters"
source configure.sh
usage() {
echo "Usage: $0 [OPTIONS]"
echo "Options:"
echo " -h, --help Display this help message"
echo " -b, --batch Enable batch mode, no ask for user"
echo " -n, --notify Use notify-send to send notifications"
}
error_ext(){
echo "${ECHO_ERRO} $1"
if $notify; then
notify-send -u critical "Backup Fail" \
"Backup fail at $(date '+%Y-%m-%d %H:%M'), reason: $1"
fi
exit 1
}
batch_mode=false
notify=false
handle_options() {
while [ $# -gt 0 ]; do
case $1 in
-h | --help)
usage
exit 0
;;
-b | --batch)
batch_mode=true
echo "batch mode: ON"
;;
-n | --notify)
notify=true
echo "notify: ON"
;;
*)
echo "Invalid option: $1" >&2
usage
exit 1
;;
esac
shift
done
}
# Main script execution
handle_options "$@"
if ! $batch_mode; then
ECHO_WARN="\033[43m[WARM]\033[0m"
ECHO_ERRO="\033[41m[ERRO]\033[0m"
COL_INFO=`tput setaf 2;`
COL_ERRO=`tput setaf 1;`
COL_WARN=`tput setaf 3;`
COL_END=`tput sgr0`
else
ECHO_WARN="[WARM]"
ECHO_ERRO="[ERRO]"
COL_INFO=""
COL_ERRO=""
COL_WARN=""
COL_END=""
fi
# STEP 0
echo "step 0: reading from configure..."
if [ ! -f "server.conf" ]; then
error_ext "The file ./server.conf does not exist."
fi
server="$(<"server.conf")"
if [ ! -f "dirs.conf" ]; then
error_ext "The file ./dirs.conf does not exist."
fi
if [ ! -f "ignores.conf" ]; then
echo "${ECHO_WARN} The file ignores.conf does not exist, create new."
touch "ignores.conf"
fi
lasttime=$(date -d "${FIRST_BACKUP}" '+%Y-%m-%d %H:%M')
if [ -f "lasttime.conf" ]; then
lasttime=$(cat "lasttime.conf")
echo "Last backup time: $lasttime"
else
echo "${ECHO_WARN} First-time backup, consider files that have been modified within the last week"
fi
declare -a dirs
while IFS= read -r dir; do
dirs+=("$dir")
done < <(grep -vE '^(\s*$|#)' "dirs.conf")
find_not_params=()
while IFS= read -r ignore; do
find_not_params+=(-path "$ignore" -o)
done < <(grep -vE '^(\s*$|#)' "ignores.conf")
# STEP 1
echo "step 1: finding recently modified UNBACKED IMPORTANT file..."
declare -a files
declare -i files_size_tot
files_size_tot=0
for i in "${!dirs[@]}"; do
echo "[$((i+1))/${#dirs[*]}] Find in ${dirs[i]}:"
if [ -d "${dirs[i]}" ]; then
# set -x
while IFS= read -r -d '' file; do
mod_time=$(stat -c "%Y" "$file")
birth_time=$(stat -c "%W" "$file")
if [ $((mod_time - birth_time)) -gt 30 ]; then
files+=("$file")
file_size=$(stat -c%s "$file")
files_size_tot=$((file_size+files_size_tot))
echo "$file $(numfmt --to=iec-i $file_size)"
else
echo "$file ${COL_WARN}presumed unimportant, skipped${COL_END}"
fi
done < <(find "${dirs[i]}" -type f -not \
\(\
"${find_not_params[@]}" \
-path '*/\.*' \
\)\
-newermt "$lasttime"\
-print0)
# set +x
else
error_ext "${dirs[i]} does not exist."
fi
done
backup_size=$(numfmt --to=iec-i $files_size_tot)
if ! $batch_mode; then
read -p "Total size of files to backup: ${COL_INFO}${backup_size}${COL_END}, continue to backup?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
exit 0
fi
fi
# STEP 2
echo "step 2: transferring files to remote server..."
dir_backup_remote="\"\$HOME/$DIR_BACKUP\""
tar czf - "${files[@]}" --atime-preserve --transform "s,.*/,&$(date '+%Y%m%d-%H%M-')," | ssh $server "tar xzf - -C "$dir_backup_remote""
if [ $? -ne 0 ]; then
error_ext "transferring fail."
fi
date '+%Y-%m-%d %H:%M' > "lasttime.conf"
# STEP 3
echo "step 3: check remote server backups..."
remote_size=$(ssh $server "du -sh $dir_backup_remote" | awk '{print $1}')
if ! $batch_mode; then
read -p "Total size of files on remote server: ${COL_INFO}$remote_size${COL_END}, continue to clean up redundant backups?(y/n) " -n 1 -r
echo
if [[ ! $REPLY =~ ^[Yy]$ ]]
then
exit 0
fi
fi
# STEP 4
echo "step 4: running remote server cleaner..."
if ! scp -C -p -B "./remote_cleaner.sh" "./configure.sh" \
$server:$dir_backup_remote; then
error_ext "transferring cleaner scripts fail."
fi
if ! ssh $server "cd $dir_backup_remote && \
chmod +x remote_cleaner.sh && \
./remote_cleaner.sh"; then
error_ext "cleaner script run fail."
fi
echo "Done."
if $notify; then
notify-send -u normal "Backup-Real-Matters Done" \
"Backup total size of backups: $backup_size, remote storage usage: $remote_size, done at $(date '+%Y-%m-%d %H:%M')"
fi