Просмотр исходного кода

Merge pull request #854 from hestiacp/fix-backup

Bugfix #850 / #848 Improve backup
Raphael Schneeberger 5 лет назад
Родитель
Сommit
2f37337f22

+ 1 - 0
CHANGELOG.md

@@ -40,6 +40,7 @@ All notable changes to this project will be documented in this file.
 - Improved "Forgot password" function prevent brute forcing.
 - Update Backup counter propperly when v-delete-user-backup ran.
 - Dropped support for Debian 8 according to EOL.
+- Improved Backup function. 
 
 ## [1.1.1] - 2020-03-24 - Hotfix
 ### Features

+ 202 - 0
bin/v-download-backup

@@ -0,0 +1,202 @@
+#!/bin/bash
+# info: Download backup
+# options: USER BACKUP 
+#
+# The function download back-up from remote server
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Import Hestia variable for cron launch
+source /etc/profile
+
+# Argument definition
+user=$1
+backup=$2
+
+# Define backup dir
+if [ -z "$BACKUP" ]; then
+    BACKUP=/backup
+fi
+
+# Includes
+source $HESTIA/func/main.sh
+source $HESTIA/func/domain.sh
+source $HESTIA/func/ip.sh
+source $HESTIA/func/db.sh
+source $HESTIA/func/rebuild.sh
+source $HESTIA/conf/hestia.conf
+
+# Defining FTP command function
+ftpc() {
+    /usr/bin/ftp -n $HOST $PORT <<EOF
+    quote USER $USERNAME
+    quote PASS $PASSWORD
+    lcd $BACKUP
+    binary
+    $1
+    $2
+    $3
+    quit
+EOF
+}
+
+# FTP backup download function
+ftp_download() {
+    source $HESTIA/conf/ftp.backup.conf
+    if [ -z "$PORT" ]; then
+        PORT='21'
+    fi
+    if [ -z $BPATH ]; then
+        ftpc "get $1"
+    else
+        ftpc "cd $BPATH" "get $1"
+    fi
+}
+
+# SFTP command function
+sftpc() {
+    expect -f "-" <<EOF "$@"
+        set timeout 60
+        set count 0
+        spawn /usr/bin/sftp -o StrictHostKeyChecking=no \
+            -o Port=$PORT $USERNAME@$HOST
+        expect {
+            "password:" {
+                send "$PASSWORD\r"
+                exp_continue
+            }
+            -re "Couldn't|(.*)disconnect|(.*)stalled|(.*)not found" {
+                set count \$argc
+                set output "Disconnected."
+                set rc $E_FTP
+                exp_continue
+            }
+            -re ".*denied.*(publickey|password)." {
+                set output "Permission denied, wrong publickey or password."
+                set rc $E_CONNECT
+            }
+            -re "\[0-9]*%" {
+                exp_continue
+            }
+            "sftp>" {
+                if {\$count < \$argc} {
+                    set arg [lindex \$argv \$count]
+                    send "\$arg\r"
+                    incr count
+                } else {
+                    send "exit\r"
+                    set output "Disconnected."
+                    if {[info exists rc] != 1} {
+                        set rc $OK
+                    }
+                }
+                exp_continue
+            }
+            timeout {
+                set output "Connection timeout."
+                set rc $E_CONNECT
+            }
+        }
+        if {[info exists output] == 1} {
+            puts "\$output"
+        }
+    exit \$rc
+EOF
+}
+
+# SFTP backup download function
+sftp_download() {
+    source $HESTIA/conf/sftp.backup.conf
+    if [ -z "$PORT" ]; then
+        PORT='22'
+    fi
+    cd $BACKUP
+    if [ -z $BPATH ]; then
+        sftpc "get $1" > /dev/null 2>&1
+    else
+        sftpc "cd $BPATH" "get $1" > /dev/null 2>&1
+    fi
+
+}
+
+# Google backup download function
+google_download() {
+    source $HESTIA/conf/google.backup.conf
+    gsutil="$HESTIA/3rdparty/gsutil/gsutil"
+    export BOTO_CONFIG="$HESTIA/conf/.google.backup.boto"
+    ${gsutil} cp gs://$BUCKET/$BPATH/$1 $BACKUP/ > /dev/null 2>&1
+    if [ "$?" -ne 0 ]; then
+        check_result "$E_CONNECT" "gsutil failed to download $1"
+    fi
+}
+
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '2' "$#" 'USER BACKUP'
+is_format_valid 'user' 'backup'
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+
+# Checking available disk space
+disk_usage=$(df $BACKUP |tail -n1 |tr ' ' '\n' |grep % |cut -f 1 -d %)
+if [ "$disk_usage" -ge "$BACKUP_DISK_LIMIT" ]; then
+    echo "Error: Not enough disk space" |$SENDMAIL -s "$subj" $email $notify
+    sed -i "/ $user /d" $HESTIA/data/queue/backup.pipe
+    check_result $E_DISK "Not enough disk space"
+fi
+
+# Checking local backup
+if [ ! -e "$BACKUP/$backup" ]; then
+    if [[ "$BACKUP_SYSTEM" =~ "google" ]]; then
+        google_download $backup
+        downloaded='yes'
+    fi
+    if [[ "$BACKUP_SYSTEM" =~ "sftp" ]] && [ -z "$downloaded" ]; then
+        sftp_download $backup
+        downloaded='yes'
+    fi
+    if [[ "$BACKUP_SYSTEM" =~ "ftp" ]] && [ -z "$downloaded" ]; then
+        ftp_download $backup
+        downloaded='yes'
+    fi
+    if [ -z "$downloaded" ]; then
+        check_result $E_NOTEXIST "backup file $backup doesn't exist in '${BACKUP}' folder"
+    else
+        if [ -e "$BACKUP/$backup" ]; then
+        chmod 0640 $BACKUP/$backup
+        chown admin:admin $BACKUP/$backup
+        echo "rm $BACKUP/$backup" | at now + 1 day
+        fi
+    fi
+fi
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+# Send notification
+if [ -e "$BACKUP/$backup" ]; then
+    cd $BACKUP
+    subj="$user → Download of $backup has been completed"
+    email=$(get_user_value '$CONTACT')
+    echo "Download of $backup has been completed you are able to download it for 12 hours" |$SENDMAIL -s "$subj" $email $notify
+    $BIN/v-add-user-notification $user "$subj" "Download of $backup has been completed you are able to download it for 12 hours"
+    
+fi
+
+# Cleaning restore queue
+sed -i "/v-download-backup $user /d" $HESTIA/data/queue/backup.pipe
+
+# Logging
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 48 - 0
bin/v-schedule-user-backup-download

@@ -0,0 +1,48 @@
+#!/bin/bash
+# info: Schedule a backup
+# options: USER BACKUP 
+#
+# The function for scheduling user backup creation.
+
+
+#----------------------------------------------------------#
+#                    Variable&Function                     #
+#----------------------------------------------------------#
+
+# Importing system variables
+source /etc/profile
+
+# Argument definition
+user=$1
+backup=$2
+
+# Includes
+source $HESTIA/func/main.sh
+source $HESTIA/func/domain.sh
+source $HESTIA/func/db.sh
+source $HESTIA/conf/hestia.conf
+
+#----------------------------------------------------------#
+#                    Verifications                         #
+#----------------------------------------------------------#
+
+check_args '2' "$#" 'USER BACKUP'
+is_format_valid 'user' 'backup'
+
+#----------------------------------------------------------#
+#                       Action                             #
+#----------------------------------------------------------#
+
+# Adding backup task to  the queue
+echo "$BIN/v-download-backup $user $backup 2>&1" >>\
+    $HESTIA/data/queue/backup.pipe
+
+
+#----------------------------------------------------------#
+#                       Hestia                             #
+#----------------------------------------------------------#
+
+# Logging
+log_event "$OK" "$ARGUMENTS"
+
+exit

+ 20 - 15
web/download/backup/index.php

@@ -1,26 +1,31 @@
 <?php
 // Init
 error_reporting(NULL);
+ob_start();
 session_start();
 include($_SERVER['DOCUMENT_ROOT']."/inc/main.php");
-$backup = basename($_GET['backup']);
 
-// Check if the backup exists
-if (!file_exists('/backup/'.$backup)) {
-    exit(0);
+// Check token
+if ((!isset($_GET['token'])) || ($_SESSION['token'] != $_GET['token'])) {
+    header('Location: /login/');
+    exit();
 }
 
-// Data
-if ($_SESSION['user'] == 'admin') {
-    header('Content-type: application/gzip');
-    header("Content-Disposition: attachment; filename=\"".$backup."\";" ); 
-    header("X-Accel-Redirect: /backup/" . $backup);
-}
+$v_username = escapeshellarg($user);
+exec (HESTIA_CMD."v-schedule-user-backup ".$v_username, $output, $return_var);
+if ($return_var == 0) {
+    $_SESSION['error_msg'] = __('BACKUP_SCHEDULED');
+} else {
+    $_SESSION['error_msg'] = implode('<br>', $output);
+    if (empty($_SESSION['error_msg'])) {
+        $_SESSION['error_msg'] = __('Error: hestia did not return any output.');
+    }
 
-if ((!empty($_SESSION['user'])) && ($_SESSION['user'] != 'admin')) {
-    if (strpos($backup, $user.'.') === 0) {
-        header('Content-type: application/gzip');
-        header("Content-Disposition: attachment; filename=\"".$backup."\";" ); 
-        header("X-Accel-Redirect: /backup/" . $backup);
+    if ($return_var == 4) {
+        $_SESSION['error_msg'] = __('BACKUP_EXISTS');
     }
+
 }
+unset($output);
+header("Location: /list/backup/");
+exit;

+ 10 - 5
web/edit/server/index.php

@@ -388,11 +388,12 @@ if (!empty($_POST['save'])) {
     if (empty($_SESSION['error_msg'])) {
         if ((!empty($_POST['v_backup_host'])) && (empty($v_backup_host))) {
             $v_backup_host = escapeshellarg($_POST['v_backup_host']);
+            $v_backup_port = escapeshellarg($_POST['v_backup_port']);
             $v_backup_type = escapeshellarg($_POST['v_backup_type']);
             $v_backup_username = escapeshellarg($_POST['v_backup_username']);
             $v_backup_password = escapeshellcmd($_POST['v_backup_password']);
             $v_backup_bpath = escapeshellarg($_POST['v_backup_bpath']);
-            exec (HESTIA_CMD."v-add-backup-host ". $v_backup_type ." ". $v_backup_host ." ". $v_backup_username ." '". $v_backup_password ."' ". $v_backup_bpath, $output, $return_var);
+            exec (HESTIA_CMD."v-add-backup-host ". $v_backup_type ." ". $v_backup_host ." ". $v_backup_username ." '". $v_backup_password ."' ". $v_backup_bpath." ".$v_backup_port, $output, $return_var);
             check_return_code($return_var,$output);
             unset($output);
             if (empty($_SESSION['error_msg'])) $v_backup_host = $_POST['v_backup_host'];
@@ -400,6 +401,7 @@ if (!empty($_POST['save'])) {
             if (empty($_SESSION['error_msg'])) $v_backup_username = $_POST['v_backup_username'];
             if (empty($_SESSION['error_msg'])) $v_backup_password = $_POST['v_backup_password'];
             if (empty($_SESSION['error_msg'])) $v_backup_bpath = $_POST['v_backup_bpath'];
+            if (empty($_SESSION['error_msg'])) $v_backup_port = $_POST['v_backup_port'];    
             $v_backup_new = 'yes';
             $v_backup_adv = 'yes';
             $v_backup_remote_adv = 'yes';
@@ -411,13 +413,13 @@ if (!empty($_POST['save'])) {
         if ((!empty($_POST['v_backup_host'])) && ($_POST['v_backup_type'] != $v_backup_type)) {
             exec (HESTIA_CMD."v-delete-backup-host '". $v_backup_type ."'", $output, $return_var);
             unset($output);
-
             $v_backup_host = escapeshellarg($_POST['v_backup_host']);
+            $v_backup_port = escapeshellarg($_POST['v_backup_port']);
             $v_backup_type = escapeshellarg($_POST['v_backup_type']);
             $v_backup_username = escapeshellarg($_POST['v_backup_username']);
             $v_backup_password = escapeshellcmd($_POST['v_backup_password']);
             $v_backup_bpath = escapeshellarg($_POST['v_backup_bpath']);
-            exec (HESTIA_CMD."v-add-backup-host ". $v_backup_type ." ". $v_backup_host ." ". $v_backup_username ." '". $v_backup_password ."' ". $v_backup_bpath, $output, $return_var);
+            exec (HESTIA_CMD."v-add-backup-host ". $v_backup_type ." ". $v_backup_host ." ". $v_backup_username ." '". $v_backup_password ."' ". $v_backup_bpath." ".$v_backup_port, $output, $return_var);
             check_return_code($return_var,$output);
             unset($output);
             if (empty($_SESSION['error_msg'])) $v_backup_host = $_POST['v_backup_host'];
@@ -425,6 +427,7 @@ if (!empty($_POST['save'])) {
             if (empty($_SESSION['error_msg'])) $v_backup_username = $_POST['v_backup_username'];
             if (empty($_SESSION['error_msg'])) $v_backup_password = $_POST['v_backup_password'];
             if (empty($_SESSION['error_msg'])) $v_backup_bpath = $_POST['v_backup_bpath'];
+            if (empty($_SESSION['error_msg'])) $v_backup_port = $_POST['v_backup_port'];
             $v_backup_adv = 'yes';
             $v_backup_remote_adv = 'yes';
         }
@@ -433,13 +436,14 @@ if (!empty($_POST['save'])) {
     // Change remote backup host
     if (empty($_SESSION['error_msg'])) {
         if ((!empty($_POST['v_backup_host'])) && ($_POST['v_backup_type'] == $v_backup_type) && (!isset($v_backup_new))) {
-            if (($_POST['v_backup_host'] != $v_backup_host) || ($_POST['v_backup_username'] != $v_backup_username) || ($_POST['v_backup_password'] != $v_backup_password) || ($_POST['v_backup_bpath'] != $v_backup_bpath)){
+            if (($_POST['v_backup_host'] != $v_backup_host) || ($_POST['v_backup_username'] != $v_backup_username) || ($_POST['v_backup_password'] != $v_backup_password) || ($_POST['v_backup_bpath'] != $v_backup_bpath || $_POST['v_backup_port'] != $v_backup_port)){
                 $v_backup_host = escapeshellarg($_POST['v_backup_host']);
+                $v_backup_port = escapeshellarg($_POST['v_backup_port']);
                 $v_backup_type = escapeshellarg($_POST['v_backup_type']);
                 $v_backup_username = escapeshellarg($_POST['v_backup_username']);
                 $v_backup_password = escapeshellcmd($_POST['v_backup_password']);
                 $v_backup_bpath = escapeshellarg($_POST['v_backup_bpath']);
-                exec (HESTIA_CMD."v-add-backup-host ". $v_backup_type ." ". $v_backup_host ." ". $v_backup_username ." '". $v_backup_password ."' ". $v_backup_bpath, $output, $return_var);
+                exec (HESTIA_CMD."v-add-backup-host ". $v_backup_type ." ". $v_backup_host ." ". $v_backup_username ." '". $v_backup_password ."' ". $v_backup_bpath." ".$v_backup_port, $output, $return_var);
                 check_return_code($return_var,$output);
                 unset($output);
                 if (empty($_SESSION['error_msg'])) $v_backup_host = $_POST['v_backup_host'];
@@ -447,6 +451,7 @@ if (!empty($_POST['save'])) {
                 if (empty($_SESSION['error_msg'])) $v_backup_username = $_POST['v_backup_username'];
                 if (empty($_SESSION['error_msg'])) $v_backup_password = $_POST['v_backup_password'];
                 if (empty($_SESSION['error_msg'])) $v_backup_bpath = $_POST['v_backup_bpath'];
+                if (empty($_SESSION['error_msg'])) $v_backup_port = $_POST['v_backup_port'];
                 $v_backup_adv = 'yes';
                 $v_backup_remote_adv = 'yes';
             }

+ 12 - 1
web/templates/admin/edit_server.html

@@ -643,7 +643,7 @@
                                                         <td>
                                                             <select class="vst-list" name="v_backup_type">
                                                                 <option value='ftp'><?php print __('ftp'); ?></option>
-                                                                <option value='sftp' <?php if((!empty($v_backup_type)) && ($v_backup_type  == 'sftp')) echo 'selected' ?> ><?php print __('sftp'); ?></option>
+                                                                <option value='sftp' <?php if((!empty($v_backup_type)) && (trim($v_backup_type,"'")  == 'sftp' )) echo 'selected="selected"'; ?>><?php print __('sftp'); ?></option>
                                                             </select>
                                                             <br><br>
                                                         </td>
@@ -659,6 +659,17 @@
                                                             <br><br>
                                                         </td>
                                                     </tr>
+                                                    <tr>
+                                                        <td class="vst-text">
+                                                            <?php print __('Port') ?>
+                                                        </td>
+                                                    </tr>
+                                                    <tr>
+                                                        <td>
+                                                            <input type="text" size="20" class="vst-input" name="v_backup_port" value="<?=trim($v_backup_port, "'")?>">
+                                                            <br><br>
+                                                        </td>
+                                                    </tr>
                                                     <tr>
                                                         <td class="vst-text">
                                                             <?php print __('Username') ?>