backup.sh 6.48 KB
Newer Older
1
2
3
4
5
6
#!/bin/bash
snipeitDirectory="/var/www/html/snipeit"
backupDirectory="$snipeitDirectory/storage/app/backups"
dbDumpFile="$snipeitDirectory/vendor/spatie/db-dumper/src/Databases/MySql.php"
destinationDir="/export/home/snipeit/backups"

7
#/ Usage: backup.sh [-dbmofh]
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
#/
#/ Create an incremental backup of a snipeit-instance
#/
#/ OPTIONS:
#/   -d | --snipeit-directory          Set the directory of the instance to be backed up
#/   -b | --backup-directory           Set the directory where SnipeIT places the internal backups
#/   -m | --mysql-dump-settings        Set the location of the database dump settings file
#/   -o | --output-directory           Set the output directory for where to place the backups
#/   -f | --full-backup                Make a new, full, backup instead of an incremental one
#/   -h | --help                       Show this message.

print_usage () {
  grep '^#/' <"$0" | cut -c 4-
  exit 1
}

#Parse arguments
while [[ $# > 0 ]]; do
  case "$1" in
    -d|--snipeit-directory)
      shift
      if test $# -gt 0; then
        snipeitDirectory=$(echo "$1" | sed "s,/$,,")
      else
        echo "No SnipeIT directory specified"
        exit 1
      fi
      shift
      ;;
    -b|--backup-directory)
      shift
      if test $# -gt 0; then
        backupDirectory=$(echo "$1" | sed "s,/$,,")
      else
        echo "No backup directory specified"
        exit 1
      fi
      shift
      ;;
    -m|--mysql-dump-settings)
      if test $# -gt 0; then
        dbDumpFile=$1
      else
        echo "No database dump settings specified"
        exit 1
      fi
      shift
      ;;
    -o|--output-directory)
      if test $# -gt 0; then
        destinationDir=$(echo "$1" | sed "s,/$,,")
      else
        echo "No output directory specified"
        exit 1
      fi
      shift
      ;;
    -f|--full-backup)
      echo "Creating full backup"
      mkdir "$destinationDir/$(date +%s)"
      shift
      ;;
    -h|--help)
      print_usage
      exit 1
      ;;
    -*)
      echo "Error: invalid argument: '$1'" 1>&2
      print_usage
      exit 1
      ;;
  esac
done

if ! [ -d "$destinationDir/" ]; then
    echo "Output directory not found: $destinationDir"
    exit 0
fi

if ! [ -d "$snipeitDirectory/" ]; then
    echo "SnipeIT directory not found: $snipeitDirectory"
    exit 0
fi

if ! [ -d "$backupDirectory/" ]; then
    echo "Backup directory not found: $backupDirectory"
    exit 0
fi

if ! [ -f "$dbDumpFile" ]; then
    echo "Database dump settings file not found: $dbDumpFile"
    exit 0
fi

102
103
dnf install -y patch php-zip diffutils

104
105
106
107
108
109
#Update value in config file to get correct format
sed -i 's/protected $useExtendedInserts = true;/protected $useExtendedInserts = false;/' $dbDumpFile

#Generate the internal backup
cd $snipeitDirectory
php artisan backup:run
OskarStenberg's avatar
OskarStenberg committed
110
backupFile=$(ls -lt $backupDirectory | head -2 | tail -1 | awk '{print $9}')
111
112
113
114
115
116
117
118
119
120
121
extractDir=$(echo $backupFile | cut -f 1 -d '.')
echo "Current backup: $extractDir"

#Create the workdir and copy all the important files to it
workdir=$(mktemp -d)
cd $workdir
echo "Tmp dir: $workdir"
mkdir new
unzip -qq "$backupDirectory/$backupFile" -d "./$extractDir" > /dev/null 2>&1
cd $extractDir
echo "Copied:"
122
find . -path ".$snipeitDirectory/public/uploads/barcodes" -prune -o -print0| egrep -zZ '(*\.png|*\.jpg|*\.webp|*\.gif|*\.svg|\.env|*csv)$' | cpio -0pdmu ../new/
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
cd ../
cp -r $extractDir/db-dumps new/

now=$(date +%s)

#If there are no previous full backups, then create one
if [ -z "$(ls -A "$destinationDir/")" ]; then
    mkdir "$destinationDir/$now"
fi

lastBackup=$(ls -lt $destinationDir | head -2 | tail -1 | awk '{print $9}')

#If there are no patches, create a folder for them
if ! [ -d "$destinationDir/$lastBackup/patches" ]; then
    mkdir "$destinationDir/$lastBackup/patches"
fi

140
141
142
143
144
#If there are no current file folders, create a folder for them
if ! [ -d "$destinationDir/$lastBackup/patches/files" ]; then
    mkdir "$destinationDir/$lastBackup/patches/files"
fi

145
146
147
148
149
150
151
152
#Check and copy all files (images, .env) that are either new or changed.
cd new
files=$(find ".$snipeitDirectory" -type f)
echo "Files to check:"
echo "$files"
echo "Trying to copy:"

while IFS= read -r file; do
153
    if ! [ -f "$destinationDir/$lastBackup/$(echo $file | cut -c 3-)" ]; then
154
155
156
        cp -u --parents "$file" "$destinationDir/$lastBackup/"
        echo "Copied $file $destinationDir/$lastBackup/$(echo $file | cut -c 3-)"
    else
157
        #If the file already exists, check if there is a newer version in the local backup. If it is newer than the original file, check if it has already been patched.
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
        if [ "$destinationDir/$lastBackup/$(echo $file | cut -c 3-)" -ot "$file" ]; then
            lastFilePatch=$(ls -lt "$destinationDir/$lastBackup/patches/files" | head -2 | tail -1 | awk '{print $9}')
            if [ "$destinationDir/$lastBackup/patches/files/$lastFilePatch/$(echo $file | cut -c 3-)" -ot "$file" ]; then
                #If there are no current file folders for this backup, create a folder for them
                if ! [ -d "$destinationDir/$lastBackup/patches/files/$now" ]; then
                    mkdir "$destinationDir/$lastBackup/patches/files/$now"
                fi
                cp --parents "$file" "$destinationDir/$lastBackup/patches/files/$now/"
                echo "Copied $file $destinationDir/$lastBackup/patches/files/$now/$(echo $file | cut -c 3-)"
            else
                echo "File is already patched: $destinationDir/$lastBackup/patches/files/$lastFilePatch/$(echo $file | cut -c 3-)"
            fi
        else
            echo "File already exists $destinationDir/$lastBackup/$(echo $file | cut -c 3-)"
        fi
173
174
175
176
177
    fi
done <<< "$files"

#Try to make a patch of the database dump
file="db-dumps/mysql-snipeit.sql"
OskarStenberg's avatar
OskarStenberg committed
178
if [ -z "$(ls -Ap "$destinationDir/$lastBackup/patches" | grep -v /)" ]; then
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
    diff -urN null $file > patch.patch
    cp "patch.patch" "$destinationDir/$lastBackup/patches/$now.patch"
    echo "Copied patch to $destinationDir/$lastBackup/patches/$now.patch"
else
    for p in "$destinationDir/$lastBackup/patches/*.patch"; do
        (patch --quiet -p1) < $p
    done
    
    result=$(diff "mysql-snipeit.sql" "$file" > "$now.patch" && echo $? || echo $?)
    
    #Only save non-empty patches
    if [ $result != 0 -a $result != 1 ]; then
        echo "Nothing to patch"
        exit 1
    fi
    if [ -s "$now.patch" ]; then
        cp "$now.patch" "$destinationDir/$lastBackup/patches/"
        echo "Copied patch to $destinationDir/$lastBackup/patches/$now.patch"
    else
        echo "Nothing to patch"
    fi
fi
201
202

rm -Rf "$backupDirectory/$backupFile"