#!/usr/bin/perl ########################################################### #::: Automatic Database Upgrade Script #::: Author: Akkadius #::: Purpose: To upgrade databases with ease and maintain versioning ########################################################### my $confile = "eqemu_config.xml"; #default open(F, "<$confile") or die "Unable to open config: $confile\n"; my $indb = 0; while() { s/\r//g; if(//i) { $indb = 1; } next unless($indb == 1); if(/<\/database>/i) { $indb = 0; last; } if(/(.*)<\/host>/i) { $host = $1; } elsif(/(.*)<\/username>/i) { $user = $1; } elsif(/(.*)<\/password>/i) { $pass = $1; } elsif(/(.*)<\/db>/i) { $db = $1; } } print " ============================================================ # EQEmu: Automatic Database Upgrade Check # ============================================================ "; use Config; print " Operating System is: $Config{osname}\n"; if($Config{osname}=~/linux/i){ $OS = "Linux"; } if($Config{osname}=~/Win|MS/i){ $OS = "Windows"; } if($OS eq "Windows"){ $has_mysql_path = `echo %PATH%`; if($has_mysql_path=~/MySQL|MariaDB/i){ @mysql = split(';', $has_mysql_path); foreach my $v (@mysql){ if($v=~/MySQL|MariaDB/i){ $path = $v . "/mysql"; last; } } print " (Windows) MySQL is in system path \n"; print " Path = " . $path . "\n"; print "============================================================\n"; } } #::: Linux Check if($OS eq "Linux"){ $has_mysql_path = `whereis mysql`; if($has_mysql_path=~/MySQL|MariaDB/i){ @mysql = split(' ', $has_mysql_path); foreach my $v (@mysql){ if($v=~/MySQL|MariaDB/i){ $path = $v; last; } } print " (Linux) MySQL is in system path \n"; print " Path = " . $path . "\n"; print "============================================================\n"; } } #::: Path not found, error and exit if($path eq ""){ print "MySQL path not found, please add the path for automatic database upgrading to continue... \n\n"; print "Exiting...\n"; exit; } #::: Create db_update working directory if not created mkdir('db_update'); # print `"$path" --user $user --password="$pass" $db < db_update/db_update_run_file.txt`; #::: Check if db_version table exists... if(GetMySQLResult("SHOW TABLES LIKE 'db_version'") eq ""){ print GetMySQLResult(" CREATE TABLE `db_version` ( `version` int(11) DEFAULT '0' ) ENGINE=InnoDB DEFAULT CHARSET=latin1; INSERT INTO `db_version` (`version`) VALUES ('1000');"); print "Table 'db_version' does not exists.... Creating...\n\n"; } @db_version = split(': ', `world db_version`); $bin_db_ver = trim($db_version[1]); $local_db_ver = trim(GetMySQLResult("SELECT `version` FROM `db_version` LIMIT 1")); print "Binary Database Version is: (" . $bin_db_ver . ")\n"; print "Local Database Version is: (" . $local_db_ver . ")\n\n"; #::: If World ran this script, and our version is up to date, continue... if($bin_db_ver == $local_db_ver && $ARGV[0] eq "ran_from_world"){ exit; } print "Retrieving latest database manifest...\n"; GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt", "db_update/db_update_manifest.txt"); # GetRemoteFile("https://dl.dropboxusercontent.com/u/50023467/dl/db_update_manifest.txt", "db_update/db_update_manifest.txt"); if($local_db_ver < $bin_db_ver){ print "You have missing database updates, type 1 or 2 to backup your database before running them as recommended...\n\n"; #::: Display Menu ShowMenuPrompt(); } sub ShowMenuPrompt { my %dispatch = ( 1 => \&database_dump, 2 => \&database_dump_compress, 3 => \&Run_Database_Check, 0 => \&Exit, ); while (1) { { local $| = 1; print MenuOptions(), '> '; } my $choice = <>; $choice =~ s/\A\s+//; $choice =~ s/\s+\z//; if (defined(my $handler = $dispatch{$choice})) { my $result = $handler->(); unless (defined $result) { exit 0; } } else { if($ARGV[0] ne "ran_from_world"){ warn "\n\nInvalid selection\n\n"; } } } } sub MenuOptions { if(defined(@total_updates)){ $option[3] = "Run pending updates... (" . scalar (@total_updates) . ")"; } else{ $option[3] = "Check for pending Database updates - Stages updates for automatic upgrade..."; } return <new; $ua->timeout(10); $ua->env_proxy; my $response = $ua->get($URL); if ($response->is_success){ open (FILE, '> ' . $Dest_File . ''); print FILE $response->decoded_content; close (FILE); print " URL: " . $URL . "\n"; print " Saved: " . $Dest_File . " \n"; } else { print "Error, no connection to the internet...\n\n"; die $response->status_line; } } if($OS eq "Linux"){ #::: wget -O db_update/db_update_manifest.txt https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/db_update_manifest.txt $wget = `wget -O $Dest_File $URL`; print " URL: " . $URL . "\n"; print " Saved: " . $Dest_File . " \n"; if($wget=~/unable to resolve/i){ print "Error, no connection to the internet...\n\n"; die; } } } #::: Trim Whitespaces sub trim { my $string = $_[0]; $string =~ s/^\s+//; $string =~ s/\s+$//; return $string; } #::: Responsible for Database Upgrade Routines sub Run_Database_Check{ #::: Run 2 - Running pending updates... if(defined(@total_updates)){ @total_updates = sort @total_updates; foreach my $val (@total_updates){ $file_name = trim($m_d{$val}[1]); print "Running Update: " . $val . " - " . $file_name . "\n"; print GetMySQLResultFromFile("db_update/$file_name"); } return; } #::: Run 1 - Initial checking of needed updates... print "Reading manifest...\n\n"; use Data::Dumper; open (FILE, "db_update/db_update_manifest.txt"); while () { chomp; $o = $_; if($o=~/#/i){ next; } #print $o . "\n"; @manifest = split('\|', $o); $m_d{$manifest[0]} = [@manifest]; } @total_updates = (); #::: Iterate through Manifest backwards from binary version down to local version... for($i = $bin_db_ver; $i > $local_db_ver; $i--){ if(!defined($m_d{$i}[0])){ next; } $file_name = trim($m_d{$i}[1]); $query_check = trim($m_d{$i}[2]); $match_type = trim($m_d{$i}[3]); $match_text = trim($m_d{$i}[4]); #::: Match type update if($match_type eq "contains"){ if(trim(GetMySQLResult($query_check))=~/$match_text/i){ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; FetchMissingUpdate($i, $file_name); push(@total_updates, $i); } else{ print "DB up to date with: " . $i . " '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "missing"){ if(GetMySQLResult($query_check)=~/$match_text/i){ print "DB up to date with: " . $i . " '" . $file_name . "' \n"; next; } else{ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; FetchMissingUpdate($i, $file_name); push(@total_updates, $i); } print_match_debug(); print_break(); } if($match_type eq "empty"){ if(GetMySQLResult($query_check) eq ""){ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; FetchMissingUpdate($i, $file_name); push(@total_updates, $i); } else{ print "DB up to date with: " . $i . " '" . $file_name . "' \n"; } print_match_debug(); print_break(); } if($match_type eq "not_empty"){ if(GetMySQLResult($query_check) ne ""){ print "Missing DB Update " . $i . " '" . $file_name . "' \n"; FetchMissingUpdate($i, $file_name); push(@total_updates, $i); } else{ print "DB up to date with: " . $i . " '" . $file_name . "' \n"; } print_match_debug(); print_break(); } } print "\n\n"; } sub FetchMissingUpdate{ $db_update = $_[0]; $update_file = $_[1]; if($db_update >= 9000){ GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/git/required/" . $update_file, "db_update/" . $update_file . ""); } elsif($db_update >= 5000 && $db_update <= 9000){ GetRemoteFile("https://raw.githubusercontent.com/EQEmu/Server/master/utils/sql/svn/" . $update_file, "db_update/" . $update_file . ""); } } sub print_match_debug{ if(!$debug){ return; } print " Match Type: '" . $match_type . "'\n"; print " Match Text: '" . $match_text . "'\n"; print " Query Check: '" . $query_check . "'\n"; print " Result: '" . trim(GetMySQLResult($query_check)) . "'\n"; } sub print_break{ if(!$debug){ return; } print "\n==============================================\n"; }