最後活躍 1697445670 Unlisted

Backup system user (without backups enabled in plan) with all its objects

sahsanu 已修改 1697445670. 還原成這個修訂版本

沒有任何變更

sahsanu 已修改 1697390153. 還原成這個修訂版本

1 file changed, 0 insertions, 0 deletions

v-backup-user-without-backups 重命名為 v-backup-user-without-backups.sh

檔案名稱與重新命名前相同

sahsanu 已修改 1697390106. 還原成這個修訂版本

1 file changed, 808 insertions

v-backup-user-without-backups(檔案已創建)

@@ -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
上一頁 下一頁