sahsanu revidoval tento gist . Přejít na revizi
Žádné změny
sahsanu revidoval tento gist . Přejít na revizi
1 file changed, 0 insertions, 0 deletions
v-backup-user-without-backups přejmenováno na v-backup-user-without-backups.sh
Soubor přejmenován beze změn
sahsanu revidoval tento gist . Přejít na revizi
1 file changed, 808 insertions
v-backup-user-without-backups(vytvořil soubor)
@@ -0,0 +1,808 @@ | |||
1 | + | #!/bin/bash | |
2 | + | # info: backup system user (without backups enabled in plan) with all its objects | |
3 | + | # options: USER | |
4 | + | # | |
5 | + | # example: v-backup-user admin yes | |
6 | + | # | |
7 | + | # This function is used for backing up user with all its domains and databases. | |
8 | + | ||
9 | + | #----------------------------------------------------------# | |
10 | + | # Variables & Functions # | |
11 | + | #----------------------------------------------------------# | |
12 | + | ||
13 | + | # Argument definition | |
14 | + | user=$1 | |
15 | + | notify=${2-no} | |
16 | + | ||
17 | + | # Includes | |
18 | + | # shellcheck source=/etc/hestiacp/hestia.conf | |
19 | + | source /etc/hestiacp/hestia.conf | |
20 | + | # shellcheck source=/usr/local/hestia/func/main.sh | |
21 | + | source $HESTIA/func/main.sh | |
22 | + | # shellcheck source=/usr/local/hestia/func/domain.sh | |
23 | + | source $HESTIA/func/domain.sh | |
24 | + | # shellcheck source=/usr/local/hestia/func/db.sh | |
25 | + | source $HESTIA/func/db.sh | |
26 | + | # shellcheck source=/usr/local/hestia/func/backup.sh | |
27 | + | source $HESTIA/func/backup.sh | |
28 | + | # load config file | |
29 | + | source_conf "$HESTIA/conf/hestia.conf" | |
30 | + | ||
31 | + | ||
32 | + | # Return Disk Usage | |
33 | + | get_user_disk_usage() { | |
34 | + | u_usage=0 | |
35 | + | web_exclusions='' | |
36 | + | mail_exclusions='' | |
37 | + | db_exclusions='' | |
38 | + | user_exclusions='' | |
39 | + | ||
40 | + | # Parsing excludes | |
41 | + | if [ -e "$USER_DATA/backup-excludes.conf" ]; then | |
42 | + | web_exclusions=$(grep 'WEB=' $USER_DATA/backup-excludes.conf \ | |
43 | + | | awk -F "WEB='" '{print $2}' | cut -f 1 -d \') | |
44 | + | mail_exclusions=$(grep 'MAIL=' $USER_DATA/backup-excludes.conf \ | |
45 | + | | awk -F "MAIL='" '{print $2}' | cut -f 1 -d \') | |
46 | + | db_exclusions=$(grep 'DB=' $USER_DATA/backup-excludes.conf \ | |
47 | + | | awk -F "DB='" '{print $2}' | cut -f 1 -d \') | |
48 | + | user_exclusions=$(grep 'USER=' $USER_DATA/backup-excludes.conf \ | |
49 | + | | awk -F "USER='" '{print $2}' | cut -f 1 -d \') | |
50 | + | fi | |
51 | + | ||
52 | + | if [ -f "$USER_DATA/web.conf" ] && [ "$web_exclusions" != '*' ]; then | |
53 | + | usage=0 | |
54 | + | domains=$(grep 'DOMAIN=' $USER_DATA/web.conf \ | |
55 | + | | awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \') | |
56 | + | ||
57 | + | for domain in $domains; do | |
58 | + | exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*$") | |
59 | + | if [ -z "$exclusion" ]; then | |
60 | + | # Defining home directory | |
61 | + | home_dir="$HOMEDIR/$user/web/$domain/" | |
62 | + | exclusion=$(echo -e "$web_exclusions" | tr ',' '\n' | grep "^$domain\|\*:") | |
63 | + | fargs=() | |
64 | + | ||
65 | + | if [ -n "$exclusion" ]; then | |
66 | + | xdirs=$(echo -e "$exclusion" | tr ':' '\n' | grep -v "$domain\|\*") | |
67 | + | for xpath in $xdirs; do | |
68 | + | fargs+=(--exclude="$xpath") | |
69 | + | done | |
70 | + | fi | |
71 | + | ||
72 | + | # Checking home directory exist | |
73 | + | if [ -e "$home_dir" ]; then | |
74 | + | disk_usage=$(nice -n 19 du -shm "$home_dir" "${fargs[@]}" | cut -f 1) | |
75 | + | u_usage=$((u_usage + disk_usage)) | |
76 | + | fi | |
77 | + | fi | |
78 | + | done | |
79 | + | fi | |
80 | + | ||
81 | + | if [ -f "$USER_DATA/mail.conf" ] && [ "$mail_exclusions" != '*' ]; then | |
82 | + | usage=0 | |
83 | + | domains=$(grep 'DOMAIN=' "$USER_DATA/mail.conf" \ | |
84 | + | | awk -F "DOMAIN='" '{print $2}' | cut -f 1 -d \') | |
85 | + | ||
86 | + | for domain in $domains; do | |
87 | + | check_exl=$(echo "$mail_exclusions" | tr ',' '\n' | grep "^$domain$") | |
88 | + | if [ -f "$USER_DATA/mail/$domain.conf" ] && [ -z "$check_exl" ]; then | |
89 | + | accounts=$(grep 'ACCOUNT=' "$USER_DATA/mail/$domain.conf" \ | |
90 | + | | awk -F "ACCOUNT='" '{print $2}' | cut -f 1 -d \') | |
91 | + | ||
92 | + | for account in $accounts; do | |
93 | + | home_dir=$HOMEDIR/$user/mail/$domain/$account | |
94 | + | exclusion=$(echo "$mail_exclusions" | tr ',' '\n' | grep "$domain:") | |
95 | + | exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*") | |
96 | + | ||
97 | + | if [ -z "$exclusion" ] && [ -e "$home_dir" ]; then | |
98 | + | disk_usage=$(nice -n 19 du -shm "$home_dir" | cut -f 1) | |
99 | + | u_usage=$((u_usage + disk_usage)) | |
100 | + | fi | |
101 | + | done | |
102 | + | fi | |
103 | + | done | |
104 | + | fi | |
105 | + | ||
106 | + | if [ -f "$USER_DATA/db.conf" ] && [ "$db_exclusions" != '*' ]; then | |
107 | + | usage=0 | |
108 | + | databases=$(grep 'DB=' "$USER_DATA/db.conf" \ | |
109 | + | | awk -F "DB='" '{print $2}' | cut -f 1 -d \') | |
110 | + | for database in $databases; do | |
111 | + | exclusion=$(echo "$db_exclusions" | tr ',' '\n' | grep "^$database$") | |
112 | + | if [ -z "$exclusion" ]; then | |
113 | + | # Get database values | |
114 | + | get_database_values | |
115 | + | ||
116 | + | # Switching on db type | |
117 | + | case $DB_SYSTEM in | |
118 | + | mysql) get_mysql_disk_usage ;; | |
119 | + | pgsql) get_pgsql_disk_usage ;; | |
120 | + | esac | |
121 | + | u_usage=$((u_usage + usage)) | |
122 | + | fi | |
123 | + | done | |
124 | + | fi | |
125 | + | ||
126 | + | if [ "$user_exclusions" != '*' ]; then | |
127 | + | fargs=() | |
128 | + | for xpath in $(echo "$user_exclusions" | tr ',' '\n'); do | |
129 | + | fargs+=(--exclude="$xpath") | |
130 | + | done | |
131 | + | usage=$(du -shm "$HOMEDIR/$user" --exclude "$HOMEDIR/$user/web" --exclude "$HOMEDIR/$user/mail" --exclude "$HOMEDIR/$user/conf" "${fargs[@]}" | cut -f 1) | |
132 | + | u_usage=$((u_usage + usage)) | |
133 | + | fi | |
134 | + | ||
135 | + | echo ${u_usage} | |
136 | + | } | |
137 | + | ||
138 | + | #----------------------------------------------------------# | |
139 | + | # Verifications # | |
140 | + | #----------------------------------------------------------# | |
141 | + | ||
142 | + | check_args '1' "$#" 'USER [NOTIFY]' | |
143 | + | is_format_valid 'user' | |
144 | + | is_system_enabled "$BACKUP_SYSTEM" 'BACKUP_SYSTEM' | |
145 | + | is_object_valid 'user' 'USER' "$user" | |
146 | + | if [ "$POLICY_BACKUP_SUSPENDED_USERS" != "yes" ]; then | |
147 | + | is_object_unsuspended 'user' 'USER' "$user" | |
148 | + | fi | |
149 | + | #is_backup_enabled | |
150 | + | # If user has backups enabled, exit | |
151 | + | BACKUPS=$(grep "^BACKUPS=" $USER_DATA/user.conf | cut -f2 -d \') | |
152 | + | if [[ "$BACKUPS" -gt '0' ]]; then | |
153 | + | check_result "$E_DISABLED" "backup for user $user is already enabled" | |
154 | + | fi | |
155 | + | ||
156 | + | # Only allow 1 backup for the user | |
157 | + | BACKUPS=1 | |
158 | + | # Perform verification if read-only mode is enabled | |
159 | + | check_hestia_demo_mode | |
160 | + | ||
161 | + | #----------------------------------------------------------# | |
162 | + | # Action # | |
163 | + | #----------------------------------------------------------# | |
164 | + | ||
165 | + | check_backup_conditions | |
166 | + | ||
167 | + | # Set backup directory if undefined | |
168 | + | if [ -z "$BACKUP" ]; then | |
169 | + | BACKUP=/backup | |
170 | + | fi | |
171 | + | ||
172 | + | # Check if backup folder exists and have the correct permission | |
173 | + | if [[ ! -d "$BACKUP" ]]; then | |
174 | + | mkdir -p $BACKUP | |
175 | + | fi | |
176 | + | if [ "$(stat -c %a "$BACKUP")" != 755 ]; then | |
177 | + | chmod 755 $BACKUP | |
178 | + | fi | |
179 | + | ||
180 | + | # Get current time | |
181 | + | start_time=$(date '+%s') | |
182 | + | ||
183 | + | # Set notification email and subject | |
184 | + | #subj="$user → backup failed" | |
185 | + | #email=$(grep CONTACT "$HESTIA/data/users/admin/user.conf" | cut -f 2 -d \') | |
186 | + | ||
187 | + | # Validate available disk space (take usage * 2, due to the backup handling) | |
188 | + | let u_disk=$(($(get_user_disk_usage) * 2)) | |
189 | + | let v_disk=$(($(stat -f --format="%a*%S" $BACKUP)))/1024/1024 | |
190 | + | ||
191 | + | if [ "$u_disk" -gt "$v_disk" ]; then | |
192 | + | let u_disk_original=$(get_user_disk_usage) | |
193 | + | # Always notify on failure | |
194 | + | echo "Not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb). https://hestiacp.com/docs/server-administration/backup-restore.html" | $SENDMAIL -s "$subj" "$email" "yes" | |
195 | + | # Deleting task from queue | |
196 | + | sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe | |
197 | + | check_result "$E_LIMIT" "not enough disk space available ($v_disk mb) to perform the backup of $user. ( $u_disk_original mb * 2 = $u_disk mb)." | |
198 | + | fi | |
199 | + | ||
200 | + | if [ -z "$BACKUP_TEMP" ]; then | |
201 | + | BACKUP_TEMP=$BACKUP | |
202 | + | fi | |
203 | + | ||
204 | + | # Creating temporary directory | |
205 | + | tmpdir=$(mktemp -p $BACKUP_TEMP -d) | |
206 | + | ||
207 | + | if [ "$?" -ne 0 ]; then | |
208 | + | echo "Can't create tmp dir $tmpdir" | $SENDMAIL -s "$subj" "$email" "yes" | |
209 | + | # Deleting task from queue | |
210 | + | sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe | |
211 | + | check_result "$E_NOTEXIST" "can't create tmp dir" | |
212 | + | fi | |
213 | + | ||
214 | + | # Backup sys configs | |
215 | + | echo "-- SYSTEM --" | tee $BACKUP/$user.log | |
216 | + | mkdir $tmpdir/hestia | |
217 | + | ||
218 | + | echo -e "$(date "+%F %T") $user.conf" | tee -a $BACKUP/$user.log | |
219 | + | cp -r $USER_DATA/user.conf $tmpdir/hestia/ | |
220 | + | cp -r $USER_DATA/ssl $tmpdir/hestia/ | |
221 | + | ||
222 | + | if [ -e "$USER_DATA/stats.log" ]; then | |
223 | + | echo -e "$(date "+%F %T") stats.log" | tee -a $BACKUP/$user.log | |
224 | + | cp -r $USER_DATA/stats.log $tmpdir/hestia/ | |
225 | + | fi | |
226 | + | ||
227 | + | if [ -e "$USER_DATA/history.log" ]; then | |
228 | + | echo -e "$(date "+%F %T") history.log" | tee -a $BACKUP/$user.log | |
229 | + | cp -r $USER_DATA/history.log $tmpdir/hestia/ | |
230 | + | fi | |
231 | + | ||
232 | + | if [ -e "$USER_DATA/backup-excludes.conf" ]; then | |
233 | + | echo -e "$(date "+%F %T") backup-excludes.conf" | tee -a $BACKUP/$user.log | |
234 | + | cp -r $USER_DATA/backup-excludes.conf $tmpdir/hestia/ | |
235 | + | fi | |
236 | + | ||
237 | + | # Backup PAM | |
238 | + | mkdir $tmpdir/pam | |
239 | + | echo -e "$(date "+%F %T") pam" | tee -a $BACKUP/$user.log | |
240 | + | grep "^$user:" /etc/passwd > $tmpdir/pam/passwd | |
241 | + | grep "^$user:" /etc/shadow > $tmpdir/pam/shadow | |
242 | + | grep "^$user:" /etc/group > $tmpdir/pam/group | |
243 | + | echo | |
244 | + | ||
245 | + | # Parsing excludes | |
246 | + | if [ -e "$USER_DATA/backup-excludes.conf" ]; then | |
247 | + | source $USER_DATA/backup-excludes.conf | |
248 | + | fi | |
249 | + | ||
250 | + | # WEB domains | |
251 | + | if [ -n "$WEB_SYSTEM" ] && [ "$WEB" != '*' ]; then | |
252 | + | echo -e "\n-- WEB --" | tee -a $BACKUP/$user.log | |
253 | + | mkdir $tmpdir/web/ | |
254 | + | ||
255 | + | # Parsing domain exclusions | |
256 | + | conf="$USER_DATA/web.conf" | |
257 | + | for domain in $(search_objects 'web' 'SUSPENDED' "*" 'DOMAIN'); do | |
258 | + | exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain$\|^\*$") | |
259 | + | if [ -z "$exclusion" ]; then | |
260 | + | web_list="$web_list $domain" | |
261 | + | else | |
262 | + | echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log | |
263 | + | fi | |
264 | + | done | |
265 | + | web_list=$(echo "$web_list" | sed -e "s/ */\ /g" -e "s/^ //") | |
266 | + | ||
267 | + | i=0 | |
268 | + | ||
269 | + | for domain in $web_list; do | |
270 | + | check_backup_conditions | |
271 | + | ((i++)) | |
272 | + | echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log | |
273 | + | mkdir -p $tmpdir/web/$domain/conf | |
274 | + | mkdir -p $tmpdir/web/$domain/hestia | |
275 | + | ||
276 | + | # Get domain variables | |
277 | + | domain_idn=$domain | |
278 | + | format_domain_idn | |
279 | + | get_domain_values 'web' | |
280 | + | ||
281 | + | # Backup web.conf | |
282 | + | cd $tmpdir/web/$domain/ | |
283 | + | conf="$USER_DATA/web.conf" | |
284 | + | grep "DOMAIN='$domain'" $conf > hestia/web.conf | |
285 | + | ||
286 | + | # Backup vhost config | |
287 | + | if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf" ]; then | |
288 | + | cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.conf* conf/ | |
289 | + | elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf" ]; then | |
290 | + | cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.conf* conf/ | |
291 | + | else | |
292 | + | # legacy format: all domain configs in single file | |
293 | + | tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.tpl" | |
294 | + | conf="$HOMEDIR/$user/conf/web/$WEB_SYSTEM.conf" | |
295 | + | get_web_config_lines "$tpl_file" "$conf" | |
296 | + | sed -n "$top_line,$bottom_line p" $conf > conf/$WEB_SYSTEM.conf | |
297 | + | fi | |
298 | + | ||
299 | + | # Backup ssl vhost | |
300 | + | if [ "$SSL" = 'yes' ]; then | |
301 | + | if [ -e "$HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf" ]; then | |
302 | + | cp $HOMEDIR/$user/conf/web/$domain/$WEB_SYSTEM.ssl.conf* conf/ | |
303 | + | elif [ -e "$HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf" ]; then | |
304 | + | cp $HOMEDIR/$user/conf/web/$domain.$WEB_SYSTEM.ssl.conf* conf/ | |
305 | + | else | |
306 | + | # legacy format: all domain configs in single file | |
307 | + | tpl_file="$WEBTPL/$WEB_SYSTEM/$WEB_BACKEND/$TPL.stpl" | |
308 | + | conf="$HOMEDIR/$user/conf/web/s$WEB_SYSTEM.conf" | |
309 | + | get_web_config_lines "$tpl_file" "$conf" | |
310 | + | sed -n "$top_line,$bottom_line p" $conf > conf/s$WEB_SYSTEM.conf | |
311 | + | fi | |
312 | + | fi | |
313 | + | ||
314 | + | # Backup proxy config | |
315 | + | if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then | |
316 | + | if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf" ]; then | |
317 | + | cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.conf* conf/ | |
318 | + | elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf" ]; then | |
319 | + | cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.conf* conf/ | |
320 | + | else | |
321 | + | # legacy format: all domain configs in single file | |
322 | + | tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.tpl" | |
323 | + | conf="$HOMEDIR/$user/conf/web/$PROXY_SYSTEM.conf" | |
324 | + | get_web_config_lines "$tpl_file" "$conf" | |
325 | + | sed -n "$top_line,$bottom_line p" $conf > conf/$PROXY_SYSTEM.conf | |
326 | + | fi | |
327 | + | fi | |
328 | + | ||
329 | + | # Backup ssl proxy config | |
330 | + | if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ] && [ "$SSL" = 'yes' ]; then | |
331 | + | if [ -e "$HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf" ]; then | |
332 | + | cp $HOMEDIR/$user/conf/web/$domain/$PROXY_SYSTEM.ssl.conf* conf/ | |
333 | + | elif [ -e "$HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf" ]; then | |
334 | + | cp $HOMEDIR/$user/conf/web/$domain.$PROXY_SYSTEM.ssl.conf* conf/ | |
335 | + | else | |
336 | + | # legacy format: all domain configs in single file | |
337 | + | tpl_file="$WEBTPL/$PROXY_SYSTEM/$PROXY.stpl" | |
338 | + | conf="$HOMEDIR/$user/conf/web/s$PROXY_SYSTEM.conf" | |
339 | + | get_web_config_lines "$tpl_file" "$conf" | |
340 | + | sed -n "$top_line,$bottom_line p" $conf > conf/s$PROXY_SYSTEM.conf | |
341 | + | fi | |
342 | + | fi | |
343 | + | ||
344 | + | domain_conf=$(grep "DOMAIN='$domain'" $conf) | |
345 | + | parse_object_kv_list_non_eval domain_conf | |
346 | + | ||
347 | + | mkdir -p template/$WEB_SYSTEM/ | |
348 | + | mkdir template/php-fpm/ | |
349 | + | ||
350 | + | if [ $WEB_BACKEND == 'php-fpm' ]; then | |
351 | + | cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.tpl template/$WEB_SYSTEM/ | |
352 | + | cp $HESTIA/data/templates/web/$WEB_SYSTEM/php-fpm/$TPL.stpl template/$WEB_SYSTEM/ | |
353 | + | cp $HESTIA/data/templates/web/php-fpm/$BACKEND.tpl template/php-fpm/ | |
354 | + | else | |
355 | + | cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.tpl template/$WEB_SYSTEM/ | |
356 | + | cp $HESTIA/data/templates/web/$WEB_SYSTEM/$TPL.stpl template/$WEB_SYSTEM/ | |
357 | + | fi | |
358 | + | if [ -n "$PROXY_SYSTEM" ] && [ -n "$PROXY" ]; then | |
359 | + | mkdir template/$PROXY_SYSTEM | |
360 | + | cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.tpl template/$PROXY_SYSTEM/ | |
361 | + | cp $HESTIA/data/templates/web/$PROXY_SYSTEM/$PROXY.stpl template/$PROXY_SYSTEM/ | |
362 | + | fi | |
363 | + | ||
364 | + | # Backup ssl certificates | |
365 | + | if [ "$SSL" = 'yes' ]; then | |
366 | + | cp $HOMEDIR/$user/conf/web/$domain/ssl/$domain.* conf/ | |
367 | + | cp $USER_DATA/ssl/$domain.* hestia/ | |
368 | + | fi | |
369 | + | ||
370 | + | # Changin dir to documentroot | |
371 | + | cd $HOMEDIR/$user/web/$domain | |
372 | + | ||
373 | + | # Define exclude arguments | |
374 | + | exclusion=$(echo -e "$WEB" | tr ',' '\n' | grep "^$domain\|\*:") | |
375 | + | set -f | |
376 | + | fargs=() | |
377 | + | fargs+=(--exclude='./logs/*') | |
378 | + | if [ -n "$exclusion" ]; then | |
379 | + | ||
380 | + | if [[ "$exclusion" =~ '*' ]]; then | |
381 | + | exclusion="${exclusion/\*/$domain}" | |
382 | + | fi | |
383 | + | ||
384 | + | xdirs="$(echo -e "$exclusion" | tr ':' '\n' | grep -v $domain)" | |
385 | + | for xpath in $xdirs; do | |
386 | + | if [ -d "$xpath" ]; then | |
387 | + | fargs+=(--exclude=$xpath/*) | |
388 | + | echo "$(date "+%F %T") excluding directory $xpath" | |
389 | + | msg="$msg\n$(date "+%F %T") excluding directory $xpath" | |
390 | + | else | |
391 | + | echo "$(date "+%F %T") excluding file $xpath" | |
392 | + | msg="$msg\n$(date "+%F %T") excluding file $xpath" | |
393 | + | fargs+=(--exclude=$xpath) | |
394 | + | fi | |
395 | + | done | |
396 | + | fi | |
397 | + | set +f | |
398 | + | ||
399 | + | # Backup files | |
400 | + | if [ "$BACKUP_MODE" = 'zstd' ]; then | |
401 | + | tar "${fargs[@]}" -cpf- * | pzstd -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.zst | |
402 | + | else | |
403 | + | tar "${fargs[@]}" -cpf- * | gzip -"$BACKUP_GZIP" - > $tmpdir/web/$domain/domain_data.tar.gz | |
404 | + | fi | |
405 | + | done | |
406 | + | ||
407 | + | # Print total | |
408 | + | if [ "$i" -eq 1 ]; then | |
409 | + | echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log | |
410 | + | else | |
411 | + | echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log | |
412 | + | fi | |
413 | + | fi | |
414 | + | ||
415 | + | # DNS domains | |
416 | + | if [ -n "$DNS_SYSTEM" ] && [ "$DNS" != '*' ]; then | |
417 | + | echo -e "\n-- DNS --" | tee -a $BACKUP/$user.log | |
418 | + | mkdir $tmpdir/dns/ | |
419 | + | ||
420 | + | # Parsing domain exclusions | |
421 | + | for domain in $(search_objects 'dns' 'SUSPENDED' "*" 'DOMAIN'); do | |
422 | + | exclusion=$(echo "$DNS" | tr ',' '\n' | grep "^$domain$") | |
423 | + | if [ -z "$exclusion" ]; then | |
424 | + | dns_list="$dns_list $domain" | |
425 | + | else | |
426 | + | echo "$(date "+%F %T") excluding $domain" | |
427 | + | msg="$msg\n$(date "+%F %T") excluding $domain" | |
428 | + | fi | |
429 | + | done | |
430 | + | dns_list=$(echo "$dns_list" | sed -e "s/ */\ /g" -e "s/^ //") | |
431 | + | ||
432 | + | i=0 | |
433 | + | for domain in $dns_list; do | |
434 | + | ((i++)) | |
435 | + | echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log | |
436 | + | domain_idn="$domain" | |
437 | + | # Building directory tree | |
438 | + | mkdir -p $tmpdir/dns/$domain/conf | |
439 | + | mkdir -p $tmpdir/dns/$domain/conf/keys | |
440 | + | mkdir -p $tmpdir/dns/$domain/hestia | |
441 | + | ||
442 | + | # Backup dns.conf | |
443 | + | cd $tmpdir/dns/$domain/ | |
444 | + | conf="$USER_DATA/dns.conf" | |
445 | + | grep "DOMAIN='$domain'" $conf > hestia/dns.conf | |
446 | + | ||
447 | + | # Backup dns recods | |
448 | + | cp $USER_DATA/dns/$domain.conf hestia/$domain.conf | |
449 | + | if [ "$DNS_SYSTEM" != 'remote' ]; then | |
450 | + | cp $HOMEDIR/$user/conf/dns/$domain.db conf/$domain.db | |
451 | + | fi | |
452 | + | # Backup DNSSEC public and private key if enabled | |
453 | + | dnssec=$(grep "DOMAIN='$domain'" $USER_DATA/dns.conf | grep "DNSSEC='yes'") | |
454 | + | if [ -n "$dnssec" ]; then | |
455 | + | format_domain_idn | |
456 | + | cp $USER_DATA/keys/K$domain_idn*.* $tmpdir/dns/$domain/conf/keys | |
457 | + | fi | |
458 | + | done | |
459 | + | ||
460 | + | # Print total | |
461 | + | if [ "$i" -eq 1 ]; then | |
462 | + | echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log | |
463 | + | else | |
464 | + | echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log | |
465 | + | fi | |
466 | + | fi | |
467 | + | ||
468 | + | # Mail domains | |
469 | + | if [ -n "$MAIL_SYSTEM" ] && [ "$MAIL" != '*' ]; then | |
470 | + | echo -e "\n-- MAIL --" | tee -a $BACKUP/$user.log | |
471 | + | mkdir $tmpdir/mail/ | |
472 | + | ||
473 | + | # Parsing domain exclusions | |
474 | + | conf="$USER_DATA/mail.conf" | |
475 | + | for domain in $(search_objects 'mail' 'SUSPENDED' "*" 'DOMAIN'); do | |
476 | + | check_exl=$(echo "$MAIL" | tr ',' '\n' | grep "^$domain$") | |
477 | + | if [ -z "$check_exl" ]; then | |
478 | + | mail_list="$mail_list $domain" | |
479 | + | else | |
480 | + | echo "$(date "+%F %T") excluding $domain" | tee -a $BACKUP/$user.log | |
481 | + | fi | |
482 | + | done | |
483 | + | mail_list=$(echo "$mail_list" | sed -e "s/ */\ /g" -e "s/^ //") | |
484 | + | ||
485 | + | i=0 | |
486 | + | for domain in $mail_list; do | |
487 | + | check_backup_conditions | |
488 | + | ((i++)) | |
489 | + | echo -e "$(date "+%F %T") $domain" | tee -a $BACKUP/$user.log | |
490 | + | mkdir -p $tmpdir/mail/$domain/conf | |
491 | + | mkdir -p $tmpdir/mail/$domain/hestia | |
492 | + | domain_idn=$domain | |
493 | + | format_domain_idn | |
494 | + | ||
495 | + | # Backup exim config | |
496 | + | if [[ "$MAIL_SYSTEM" =~ exim ]]; then | |
497 | + | cd $tmpdir/mail/$domain/ | |
498 | + | cp -r $HOMEDIR/$user/conf/mail/$domain/* conf/ | |
499 | + | fi | |
500 | + | ||
501 | + | # Backup mail.conf | |
502 | + | conf="$USER_DATA/mail.conf" | |
503 | + | grep "DOMAIN='$domain'" $conf > hestia/mail.conf | |
504 | + | cp $USER_DATA/mail/$domain.* hestia/ | |
505 | + | if [ -n "$(ls $USER_DATA/mail/ | grep *@$domain)" ]; then | |
506 | + | cp $USER_DATA/mail/*@$domain.* hestia/ | |
507 | + | fi | |
508 | + | ||
509 | + | # Backup emails | |
510 | + | cd $HOMEDIR/$user/mail/$domain_idn | |
511 | + | accounts=() | |
512 | + | for account in *; do | |
513 | + | exclusion=$(echo "$MAIL" | tr ',' '\n' | grep "$domain:") | |
514 | + | exclusion=$(echo "$exclusion" | tr ':' '\n' | grep -E "^$account|\*") | |
515 | + | ||
516 | + | # Checking exclusions | |
517 | + | if [ -z "$exclusion" ] && [[ "$MAIL_SYSTEM" =~ exim ]]; then | |
518 | + | accounts+=($account) | |
519 | + | else | |
520 | + | echo "$(date "+%F %T") excluding mail account $account" \ | |
521 | + | | tee -a $BACKUP/$user.log | |
522 | + | fi | |
523 | + | done | |
524 | + | # Compress archive | |
525 | + | if [ ${#accounts[@]} -gt 0 ]; then | |
526 | + | if [ "$BACKUP_MODE" = 'zstd' ]; then | |
527 | + | tar -cpf- "${accounts[@]}" | pzstd -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.zst | |
528 | + | else | |
529 | + | tar -cpf- "${accounts[@]}" | gzip -"$BACKUP_GZIP" - > $tmpdir/mail/$domain/accounts.tar.gz | |
530 | + | fi | |
531 | + | fi | |
532 | + | done | |
533 | + | ||
534 | + | # Print total | |
535 | + | if [ "$i" -eq 1 ]; then | |
536 | + | echo -e "$(date "+%F %T") *** $i domain ***" | tee -a $BACKUP/$user.log | |
537 | + | else | |
538 | + | echo -e "$(date "+%F %T") *** $i domains ***" | tee -a $BACKUP/$user.log | |
539 | + | fi | |
540 | + | fi | |
541 | + | ||
542 | + | # Databases | |
543 | + | if [ -n "$DB_SYSTEM" ] && [ "$DB" != '*' ]; then | |
544 | + | echo -e "\n-- DB --" | tee -a $BACKUP/$user.log | |
545 | + | mkdir $tmpdir/db/ | |
546 | + | ||
547 | + | # Parsing database exclusions | |
548 | + | for database in $(search_objects 'db' 'SUSPENDED' "*" 'DB'); do | |
549 | + | exclusion=$(echo "$DB" | tr ',' '\n' | grep "^$database$") | |
550 | + | if [ -z "$exclusion" ]; then | |
551 | + | db_list="$db_list $database" | |
552 | + | else | |
553 | + | echo "$(date "+%F %T") excluding $database" \ | |
554 | + | | tee -a $BACKUP/$user.log | |
555 | + | fi | |
556 | + | done | |
557 | + | ||
558 | + | i=0 | |
559 | + | conf="$USER_DATA/db.conf" | |
560 | + | db_list=$(echo "$db_list" | sed -e "s/ */\ /g" -e "s/^ //") | |
561 | + | for database in $db_list; do | |
562 | + | check_backup_conditions | |
563 | + | ((i++)) | |
564 | + | get_database_values | |
565 | + | ||
566 | + | echo -e "$(date "+%F %T") $database ($TYPE)" | tee -a $BACKUP/$user.log | |
567 | + | mkdir -p $tmpdir/db/$database/conf | |
568 | + | mkdir -p $tmpdir/db/$database/hestia | |
569 | + | ||
570 | + | cd $tmpdir/db/$database/ | |
571 | + | grep "DB='$database'" $conf > hestia/db.conf | |
572 | + | ||
573 | + | dump="$tmpdir/db/$database/$database.$TYPE.sql" | |
574 | + | if [ "$BACKUP_MODE" = 'zstd' ]; then | |
575 | + | dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.zst" | |
576 | + | else | |
577 | + | dumpgz="$tmpdir/db/$database/$database.$TYPE.sql.gz" | |
578 | + | fi | |
579 | + | ||
580 | + | grants="$tmpdir/db/$database/conf/$database.$TYPE.$DBUSER" | |
581 | + | if [ ! -f "$dumpgz" ]; then | |
582 | + | ||
583 | + | WAIT_LOOP_ENTERED=0 | |
584 | + | while true; do | |
585 | + | if pgrep -x "mysqldump" > /dev/null; then | |
586 | + | WAIT_LOOP_ENTERED=1 | |
587 | + | echo "Wait other mysqldump to finish" | |
588 | + | sleep 1 | |
589 | + | else | |
590 | + | if [ "$WAIT_LOOP_ENTERED" -eq 1 ]; then | |
591 | + | echo "We can use mysqldump now" | |
592 | + | fi | |
593 | + | break | |
594 | + | fi | |
595 | + | done | |
596 | + | ||
597 | + | case $TYPE in | |
598 | + | mysql) dump_mysql_database ;; | |
599 | + | pgsql) dump_pgsql_database ;; | |
600 | + | esac | |
601 | + | ||
602 | + | # Compress dump | |
603 | + | if [ "$BACKUP_MODE" = 'zstd' ]; then | |
604 | + | pzstd -$BACKUP_GZIP $dump | |
605 | + | rm $dump | |
606 | + | else | |
607 | + | gzip -$BACKUP_GZIP $dump | |
608 | + | fi | |
609 | + | fi | |
610 | + | done | |
611 | + | ||
612 | + | # Print total | |
613 | + | if [ "$i" -eq 1 ]; then | |
614 | + | echo -e "$(date "+%F %T") *** $i database ***" \ | |
615 | + | | tee -a $BACKUP/$user.log | |
616 | + | else | |
617 | + | echo -e "$(date "+%F %T") *** $i databases ***" \ | |
618 | + | | tee -a $BACKUP/$user.log | |
619 | + | fi | |
620 | + | fi | |
621 | + | ||
622 | + | # Cron jobs | |
623 | + | if [ -n "$CRON_SYSTEM" ] && [ "$CRON" != '*' ]; then | |
624 | + | echo -e "\n-- CRON --" | tee -a $BACKUP/$user.log | |
625 | + | mkdir $tmpdir/cron/ | |
626 | + | ||
627 | + | # Backup cron.conf | |
628 | + | cp $USER_DATA/cron.conf $tmpdir/cron/ | |
629 | + | cron_record=$(wc -l $USER_DATA/cron.conf | cut -f 1 -d ' ') | |
630 | + | ||
631 | + | if [ -e "/var/spool/cron/$user" ]; then | |
632 | + | cron_list="$cron_record" | |
633 | + | cp /var/spool/cron/$user $tmpdir/cron/ | |
634 | + | fi | |
635 | + | ||
636 | + | # Print total | |
637 | + | if [ "$cron_record" -eq 1 ]; then | |
638 | + | echo -e "$(date "+%F %T") *** $cron_record job ***" \ | |
639 | + | | tee -a $BACKUP/$user.log | |
640 | + | else | |
641 | + | echo -e "$(date "+%F %T") *** $cron_record jobs ***" \ | |
642 | + | | tee -a $BACKUP/$user.log | |
643 | + | fi | |
644 | + | fi | |
645 | + | ||
646 | + | # User Directories | |
647 | + | if [ "$USER" != '*' ]; then | |
648 | + | echo -e "\n-- User Dir --" | tee -a $BACKUP/$user.log | |
649 | + | mkdir $tmpdir/user_dir | |
650 | + | cd $HOMEDIR/$user | |
651 | + | ||
652 | + | # Parsing directory exclusions | |
653 | + | USER='' | |
654 | + | if [ -e "$USER_DATA/backup-excludes.conf" ]; then | |
655 | + | source $USER_DATA/backup-excludes.conf | |
656 | + | fi | |
657 | + | fargs=() | |
658 | + | for xpath in $(echo "$USER" | tr ',' '\n'); do | |
659 | + | if [ -d "$xpath" ]; then | |
660 | + | fargs+=(--exclude="$xpath"/*) | |
661 | + | echo "$(date "+%F %T") excluding directory $xpath" \ | |
662 | + | | tee -a $BACKUP/$user.log | |
663 | + | else | |
664 | + | echo "$(date "+%F %T") excluding file $xpath" \ | |
665 | + | | tee -a $BACKUP/$user.log | |
666 | + | fargs+=(--exclude="$xpath") | |
667 | + | fi | |
668 | + | done | |
669 | + | ||
670 | + | IFS=$'\n' | |
671 | + | set -f | |
672 | + | i=0 | |
673 | + | ||
674 | + | for udir in $(ls -a | egrep -v "^conf$|^web$|^dns$|^tmp$|^mail$|^\.\.$|^\.$"); do | |
675 | + | exclusion=$(echo "$USER" | tr ',' '\n' | grep "^$udir$") | |
676 | + | if [ -z "$exclusion" ]; then | |
677 | + | ((i++)) | |
678 | + | udir_list="$udir_list $udir" | |
679 | + | echo -e "$(date "+%F %T") adding $udir" | tee -a $BACKUP/$user.log | |
680 | + | ||
681 | + | check_backup_conditions | |
682 | + | ||
683 | + | # Backup files and dirs | |
684 | + | if [ "$BACKUP_MODE" = 'zstd' ]; then | |
685 | + | tar --anchored -cpf- "${fargs[@]}" $udir | pzstd -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.zst | |
686 | + | else | |
687 | + | tar --anchored -cpf- "${fargs[@]}" $udir | gzip -"$BACKUP_GZIP" - > $tmpdir/user_dir/$udir.tar.gz | |
688 | + | fi | |
689 | + | ||
690 | + | fi | |
691 | + | done | |
692 | + | set +f | |
693 | + | udir_list=$(echo "$udir_list" | sed -e "s/ */\ /g" -e "s/^ //") | |
694 | + | ||
695 | + | # Print total | |
696 | + | if [ "$i" -eq 1 ]; then | |
697 | + | echo -e "$(date "+%F %T") *** $i user directory ***" \ | |
698 | + | | tee -a $BACKUP/$user.log | |
699 | + | else | |
700 | + | echo -e "$(date "+%F %T") *** $i directories ***" \ | |
701 | + | | tee -a $BACKUP/$user.log | |
702 | + | fi | |
703 | + | fi | |
704 | + | ||
705 | + | if [ "$BACKUP_MODE" = 'zstd' ]; then | |
706 | + | touch $tmpdir/.zstd | |
707 | + | fi | |
708 | + | ||
709 | + | # Get backup size | |
710 | + | size="$(du -shm $tmpdir | cut -f 1)" | |
711 | + | ||
712 | + | # Get current time | |
713 | + | end_time=$(date '+%s') | |
714 | + | time_n_date=$(date +'%T %F') | |
715 | + | time=$(echo "$time_n_date" | cut -f 1 -d \ ) | |
716 | + | date=$(echo "$time_n_date" | cut -f 2 -d \ ) | |
717 | + | backup_new_date=$(date +"%Y-%m-%d_%H-%M-%S") | |
718 | + | ||
719 | + | echo -e "\n-- SUMMARY --" | tee -a $BACKUP/$user.log | |
720 | + | ||
721 | + | errorcode="0" | |
722 | + | # Switching on backup system types | |
723 | + | for backup_type in $(echo -e "${BACKUP_SYSTEM//,/\\n}"); do | |
724 | + | case $backup_type in | |
725 | + | local) local_backup ;; | |
726 | + | ftp) ftp_backup ;; | |
727 | + | sftp) sftp_backup ;; | |
728 | + | b2) b2_backup ;; | |
729 | + | rclone) rclone_backup ;; | |
730 | + | esac | |
731 | + | done | |
732 | + | ||
733 | + | # Removing tmpdir | |
734 | + | rm -rf $tmpdir | |
735 | + | if [[ "$errorcode" != "0" ]]; then | |
736 | + | if [[ "$BACKUP_SYSTEM" =~ "local" ]]; then | |
737 | + | echo -e "$(date "+%F %T") *** Local backup was successfully executed. Remote backup failed ***" \ | |
738 | + | | tee -a $BACKUP/$user.log | |
739 | + | BACKUP_SYSTEM="local" | |
740 | + | else | |
741 | + | echo -e "$(date "+%F %T") *** Remote backup failed ***" \ | |
742 | + | | tee -a $BACKUP/$user.log | |
743 | + | ||
744 | + | exit $error_code | |
745 | + | fi | |
746 | + | fi | |
747 | + | # Calculation run time | |
748 | + | run_time=$((end_time - start_time)) | |
749 | + | run_time=$((run_time / 60)) | |
750 | + | current_time=$(date "+%T") | |
751 | + | if [ "$run_time" -lt 1 ]; then | |
752 | + | run_time=1 | |
753 | + | fi | |
754 | + | min=minutes | |
755 | + | if [ "$run_time" -eq 1 ]; then | |
756 | + | min=minute | |
757 | + | fi | |
758 | + | ||
759 | + | echo "$(date "+%F %T") Size: $size MB" | tee -a $BACKUP/$user.log | |
760 | + | echo "$(date "+%F %T") Runtime: $run_time $min" | tee -a $BACKUP/$user.log | |
761 | + | ||
762 | + | #----------------------------------------------------------# | |
763 | + | # Hestia # | |
764 | + | #----------------------------------------------------------# | |
765 | + | ||
766 | + | # Removing duplicate | |
767 | + | #touch $USER_DATA/backup.conf | |
768 | + | #sed -i "/$user.$backup_new_date.tar/d" $USER_DATA/backup.conf | |
769 | + | ||
770 | + | # Registering new backup | |
771 | + | #backup_str="BACKUP='$user.$backup_new_date.tar'" | |
772 | + | #backup_str="$backup_str TYPE='$BACKUP_SYSTEM' SIZE='$size'" | |
773 | + | #backup_str="$backup_str WEB='${web_list// /,}'" | |
774 | + | #backup_str="$backup_str DNS='${dns_list// /,}'" | |
775 | + | #backup_str="$backup_str MAIL='${mail_list// /,}'" | |
776 | + | #backup_str="$backup_str DB='${db_list// /,}'" | |
777 | + | #backup_str="$backup_str CRON='$cron_list'" | |
778 | + | #backup_str="$backup_str UDIR='${udir_list// /,}'" | |
779 | + | #backup_str="$backup_str RUNTIME='$run_time' TIME='$time' DATE='$date'" | |
780 | + | #echo "$backup_str" >> $USER_DATA/backup.conf | |
781 | + | ||
782 | + | # Removing old backups | |
783 | + | #tail -n $BACKUPS $USER_DATA/backup.conf > $USER_DATA/backup.conf_ | |
784 | + | #mv -f $USER_DATA/backup.conf_ $USER_DATA/backup.conf | |
785 | + | #chmod 660 $USER_DATA/backup.conf | |
786 | + | #chmod 660 $BACKUP/$user.log | |
787 | + | ||
788 | + | # Deleting task from queue | |
789 | + | sed -i "/v-backup-user $user /d" $HESTIA/data/queue/backup.pipe | |
790 | + | ||
791 | + | #U_BACKUPS=$(grep BACKUP $USER_DATA/backup.conf | wc -l) | |
792 | + | #update_user_value "$user" '$U_BACKUPS' "$U_BACKUPS" | |
793 | + | cd $BACKUP | |
794 | + | ||
795 | + | # Send notification | |
796 | + | #if [ -e "$BACKUP/$user.log" ] && [ "$notify" = "yes" ]; then | |
797 | + | # subj="$user → backup has been completed" | |
798 | + | # email=$(get_user_value '$CONTACT') | |
799 | + | # cat $BACKUP/$user.log | $SENDMAIL -s "$subj" "$email" "$notify" | |
800 | + | # $BIN/v-add-user-notification "$user" "Backup created successfully" "<p><span class='u-text-bold'>Archive:</span> <code>$user.$backup_new_date.tar</code></p>" | |
801 | + | #fi | |
802 | + | ||
803 | + | # Logging | |
804 | + | #$BIN/v-log-action "$user" "Info" "Backup" "Backup created (Archive: $backup_new_date.tar)." | |
805 | + | $BIN/v-log-action "system" "Info" "Backup" "Backup created (User: $user, Archive: $backup_new_date.tar)." | |
806 | + | log_event "$OK" "$ARGUMENTS" | |
807 | + | ||
808 | + | exit |