1#!/usr/local/bin/perl 2# -- 3# Copyright (C) 2001-2020 OTRS AG, https://otrs.com/ 4# -- 5# This program is free software: you can redistribute it and/or modify 6# it under the terms of the GNU General Public License as published by 7# the Free Software Foundation, either version 3 of the License, or 8# (at your option) any later version. 9# 10# This program is distributed in the hope that it will be useful, 11# but WITHOUT ANY WARRANTY; without even the implied warranty of 12# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 13# GNU General Public License for more details. 14# 15# You should have received a copy of the GNU General Public License 16# along with this program. If not, see https://www.gnu.org/licenses/gpl-3.0.txt. 17# -- 18 19use strict; 20use warnings; 21 22# use ../ as lib location 23use File::Basename; 24use File::Spec qw(catfile); 25use FindBin qw($RealBin); 26use lib dirname($RealBin); 27use lib dirname($RealBin) . "/Kernel/cpan-lib"; 28 29use Getopt::Std; 30 31use Kernel::System::ObjectManager; 32 33# get options 34my %Opts; 35my $DB = ''; 36my $DBDump = ''; 37my $DecompressCMD = ''; 38my $Installed = 0; 39getopt( 'hbd', \%Opts ); 40if ( exists $Opts{h} ) { 41 print <<EOF; 42 43Restore an OTRS system from backup. 44 45Usage: 46 restore.pl -b /data_backup/<TIME>/ -d /opt/otrs/ 47 48Options: 49 -b - Directory of the backup files. 50 -d - Target OTRS home directory. 51 [-h] - Display help for this command. 52 53EOF 54 exit 1; 55} 56if ( !$Opts{b} ) { 57 print STDERR "ERROR: Need -b for backup directory\n"; 58 exit 1; 59} 60elsif ( !-d $Opts{b} ) { 61 print STDERR "ERROR: No such directory: $Opts{b}\n"; 62 exit 1; 63} 64if ( !$Opts{d} ) { 65 print STDERR "ERROR: Need -d for destination directory\n"; 66 exit 1; 67} 68elsif ( !-d $Opts{d} ) { 69 print STDERR "ERROR: No such directory: $Opts{d}\n"; 70 exit 1; 71} 72 73if ( -e File::Spec->catfile( $Opts{b}, 'DatabaseBackup.sql.bz2' ) ) { 74 $DecompressCMD = 'bunzip2'; 75} 76else { 77 $DecompressCMD = 'gunzip'; 78} 79 80# check needed programs 81for my $CMD ( 'cp', 'tar', $DecompressCMD ) { 82 $Installed = 0; 83 open( my $Input, '-|', "which $CMD" ); ## no critic 84 while (<$Input>) { 85 $Installed = 1; 86 } 87 close $Input; 88 if ( !$Installed ) { 89 print STDERR "ERROR: Can't locate $CMD!\n"; 90 exit 1; 91 } 92} 93 94# restore config 95chdir( $Opts{d} ); 96 97my $ConfigBackupGz = File::Spec->catfile( $Opts{b}, 'Config.tar.gz' ); 98my $ConfigBackupBz2 = File::Spec->catfile( $Opts{b}, 'Config.tar.bz2' ); 99if ( -e $ConfigBackupGz ) { 100 print "Restore $ConfigBackupGz ...\n"; 101 system("tar -xzf $ConfigBackupGz"); 102} 103elsif ( -e $ConfigBackupBz2 ) { 104 print "Restore $ConfigBackupBz2 ...\n"; 105 system("tar -xjf $ConfigBackupBz2"); 106} 107 108# create common objects 109local $Kernel::OM = Kernel::System::ObjectManager->new( 110 'Kernel::System::Log' => { 111 LogPrefix => 'OTRS-restore.pl', 112 }, 113); 114 115my $DatabaseHost = $Kernel::OM->Get('Kernel::Config')->Get('DatabaseHost'); 116my $Database = $Kernel::OM->Get('Kernel::Config')->Get('Database'); 117my $DatabaseUser = $Kernel::OM->Get('Kernel::Config')->Get('DatabaseUser'); 118my $DatabasePw = $Kernel::OM->Get('Kernel::Config')->Get('DatabasePw'); 119my $DatabaseDSN = $Kernel::OM->Get('Kernel::Config')->Get('DatabaseDSN'); 120my $ArticleDir = $Kernel::OM->Get('Kernel::Config')->Get('Ticket::Article::Backend::MIMEBase::ArticleDataDir'); 121 122# decrypt pw (if needed) 123if ( $DatabasePw =~ m/^\{(.*)\}$/ ) { 124 $DatabasePw = $Kernel::OM->Get('Kernel::System::DB')->_Decrypt($1); 125} 126 127# check db backup support 128if ( $DatabaseDSN =~ m/:mysql/i ) { 129 $DB = 'MySQL'; 130 $DBDump = 'mysql'; 131 132 $Installed = 0; 133 open( my $Input, '-|', "which $DBDump" ); ## no critic 134 while (<$Input>) { 135 $Installed = 1; 136 } 137 close $Input; 138 if ( !$Installed ) { 139 print STDERR "ERROR: Can't locate $DBDump!\n"; 140 exit 1; 141 } 142} 143elsif ( $DatabaseDSN =~ m/:pg/i ) { 144 $DB = 'PostgreSQL'; 145 $DBDump = 'psql'; 146 if ( $DatabaseDSN !~ m/host=/i ) { 147 $DatabaseHost = ''; 148 } 149 150 $Installed = 0; 151 open( my $Input, '-|', "which $DBDump" ); ## no critic 152 while (<$Input>) { 153 $Installed = 1; 154 } 155 close $Input; 156 if ( !$Installed ) { 157 print STDERR "ERROR: Can't locate $DBDump!\n"; 158 exit 1; 159 } 160} 161else { 162 print STDERR "ERROR: Can't backup, no database dump support!\n"; 163 exit 1; 164} 165 166# check database env 167if ( $DB =~ m/mysql/i ) { 168 $Kernel::OM->Get('Kernel::System::DB')->Prepare( SQL => "SHOW TABLES" ); 169 my $Check = 0; 170 while ( my @RowTmp = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) { 171 $Check++; 172 } 173 if ($Check) { 174 print STDERR 175 "ERROR: Already existing tables in this database. A empty database is required for restore!\n"; 176 exit 1; 177 } 178} 179else { 180 $Kernel::OM->Get('Kernel::System::DB')->Prepare( 181 SQL => 182 "SELECT table_name FROM information_schema.tables WHERE table_catalog = 'otrs' AND table_schema = 'public'", 183 ); 184 my $Check = 0; 185 while ( my @RowTmp = $Kernel::OM->Get('Kernel::System::DB')->FetchrowArray() ) { 186 $Check++; 187 } 188 if ($Check) { 189 print STDERR 190 "ERROR: Already existing tables in this database. A empty database is required for restore!\n"; 191 exit 1; 192 } 193} 194 195# restore 196my $Home = $Kernel::OM->Get('Kernel::Config')->Get('Home'); 197chdir($Home); 198 199# extract application 200my $ApplicationBackupGz = File::Spec->catfile( $Opts{b}, 'Application.tar.gz' ); 201my $ApplicationBackupBz2 = File::Spec->catfile( $Opts{b}, 'Application.tar.bz2' ); 202if ( -e $ApplicationBackupGz ) { 203 print "Restore $ApplicationBackupGz ...\n"; 204 system("tar -xzf $ApplicationBackupGz"); 205} 206elsif ( -e $ApplicationBackupBz2 ) { 207 print "Restore $ApplicationBackupBz2 ...\n"; 208 system("tar -xjf $ApplicationBackupBz2"); 209} 210 211# extract vardir 212my $VarDirBackupGz = File::Spec->catfile( $Opts{b}, 'VarDir.tar.gz' ); 213my $VarDirBackupBz2 = File::Spec->catfile( $Opts{b}, 'VarDir.tar.bz2' ); 214if ( -e $VarDirBackupGz ) { 215 print "Restore $VarDirBackupGz ...\n"; 216 system("tar -xzf $VarDirBackupGz"); 217} 218elsif ( -e $VarDirBackupBz2 ) { 219 print "Restore $VarDirBackupBz2 ...\n"; 220 system("tar -xjf $VarDirBackupBz2"); 221} 222 223# extract datadir 224my $DataDirBackupGz = File::Spec->catfile( $Opts{b}, 'DataDir.tar.gz' ); 225my $DataDirBackupBz2 = File::Spec->catfile( $Opts{b}, 'DataDir.tar.bz2' ); 226if ( -e $DataDirBackupGz ) { 227 print "Restore $DataDirBackupGz ...\n"; 228 system("tar -xzf $DataDirBackupGz"); 229} 230if ( -e $DataDirBackupBz2 ) { 231 print "Restore $DataDirBackupBz2 ...\n"; 232 system("tar -xjf $DataDirBackupBz2"); 233} 234 235# import database 236my $DatabaseBackupGz = File::Spec->catfile( $Opts{b}, 'DatabaseBackup.sql.gz' ); 237my $DatabaseBackupBz2 = File::Spec->catfile( $Opts{b}, 'DatabaseBackup.sql.bz2' ); 238if ( $DB =~ m/mysql/i ) { 239 print "create $DB\n"; 240 if ($DatabasePw) { 241 $DatabasePw = "-p'$DatabasePw'"; 242 } 243 if ( -e $DatabaseBackupGz ) { 244 print "Restore database into $DB ...\n"; 245 system( 246 "gunzip -c $DatabaseBackupGz | mysql -f -u$DatabaseUser $DatabasePw -h$DatabaseHost $Database" 247 ); 248 } 249 elsif ( -e $DatabaseBackupBz2 ) { 250 print "Restore database into $DB ...\n"; 251 system( 252 "bunzip2 -c $DatabaseBackupBz2 | mysql -f -u$DatabaseUser $DatabasePw -h$DatabaseHost $Database" 253 ); 254 } 255} 256else { 257 if ($DatabaseHost) { 258 $DatabaseHost = "-h $DatabaseHost"; 259 } 260 261 if ( -e $DatabaseBackupGz ) { 262 263 # set password via environment variable if there is one 264 if ($DatabasePw) { 265 $ENV{'PGPASSWORD'} = $DatabasePw; ## no critic 266 } 267 print "Restore database into $DB ...\n"; 268 system( 269 "gunzip -c $DatabaseBackupGz | psql -U$DatabaseUser $DatabaseHost $Database" 270 ); 271 } 272 elsif ( -e $DatabaseBackupBz2 ) { 273 274 # set password via environment variable if there is one 275 if ($DatabasePw) { 276 $ENV{'PGPASSWORD'} = $DatabasePw; ## no critic 277 } 278 print "Restore database into $DB ...\n"; 279 system( 280 "bunzip2 -c $DatabaseBackupBz2 | psql -U$DatabaseUser $DatabaseHost $Database" 281 ); 282 } 283} 284