/** * Enable you to create a database backup * * @param string $method Hotcopy or Dump method * @param string $username Access database * @param string $password Authenticate user * @param string $hostname Database server * @param string $port MySQL port * @param string $database Database to backup, ie mediboard * @param string $backupPath Backup path, ie /var/backup * @param string $time Time in days before removal of files * @param string $binary To create mysql binary log index * @param string $loginUsername Username used to send a mail when diskfull is detected * @param string $loginPassword Password for the username used to send a mail when diskfull is detected * * @return void */ function baseBackup($method, $username, $password, $hostname, $port, $database, $backupPath, $time, $binary, $loginUsername, $loginPassword, $lockFilePath = null) { $currentDir = dirname(__FILE__); $event = $currentDir . "/../tmp/monitevent.txt"; announce_script("Database daily backup"); if ($hostname === "") { $hostname = "localhost"; } if ($port === "") { $port = "3306"; } if ($time === "") { $time = "7"; } $binary = false; if ($binary === "y") { $binary = true; } if ($loginUsername === "") { $loginUsername = ""; $loginPassword = ""; } info_script("Backuping " . $database . " database"); // Make complete path // // Make shell path $SHELL_PATH = $currentDir; // Create the lock file if ($lockFilePath) { if (!check_errs(touch($lockFilePath), false, "Unable to create lock file", "Lock file created")) { return; } } // Make backup path force_dir($backupPath); // Make database path $BASE_PATH = $backupPath . "/" . $database . "-db"; force_dir($BASE_PATH); chdir($BASE_PATH); // If no enough free disk space (1.5 * size of database), send mail if provided and quit $mysql_conf = shell_exec("find /etc -name my.cnf 2>/dev/null|head -n 1"); $mysql_conf = trim($mysql_conf); $mysql_data_root = ""; $lines = file($mysql_conf); foreach ($lines as $line) { if (preg_match("/^(datadir)/m", $line)) { $datadirPOS = strpos($line, "="); $mysql_data_root = trim(substr($line, $datadirPOS + 1)); } } $dir = opendir($mysql_data_root); check_errs($dir, false, "Unable to determine MySQL data root", "MySQL data root found!"); closedir($dir); $mysql_data_base = $mysql_data_root . "/" . trim($database); $database_size = 0; $database_files = getFiles($mysql_data_base . "/"); if ($database_files) { foreach ($database_files as $one_database_file) { $database_size += filesize($one_database_file); } } // Expanded size (database + tar) $needed_size = $database_size * 3 / 2; $available_size = disk_free_space($backupPath); if ($available_size < $needed_size) { if ($loginUsername != "") { info_script("Send a mail using " . $loginUsername . " login"); // Name of the instance of mediboard $instance = basename(dirname($currentDir)); file_get_contents("http://localhost/" . $instance . "/?login="******":" . $loginPassword . "&m=system&a=ajax_send_mail_diskfull"); } } check_errs($available_size < $needed_size, 1, "Needed space " . formatSize($needed_size) . " exceeds available space " . formatSize($available_size), "Enough available space!"); // Male MySQL method // // removes previous hotcopy/dump if something went wrong rrmdir($database); $DATETIME = date('Y-m-d\\TH-i-s'); switch ($method) { case "hotcopy": $result = $database . "/"; $mysqlhotcopy = shell_exec("mysqlhotcopy -h " . $hostname . " -P " . $port . " -u " . $username . " -p " . $password . " " . $database . " " . $BASE_PATH); check_errs($mysqlhotcopy, null, "Failed to create MySQL hot copy", "MySQL hot copy done!"); if ($binary) { $link = mysql_connect($hostname . ":" . $port, $username, $password); check_errs($link, false, "Could not connect : " . mysql_error(), "Connected!"); if (!$link) { if ($lockFilePath) { unlink($lockFilePath); } return 0; } $query = "SHOW MASTER STATUS"; $res = mysql_query($query); mysql_close($link); $row = 0; if ($res) { $row = mysql_fetch_object($res); } $a = 0; if ($row) { $file = fopen($backupPath . "/binlog-" . $DATETIME . ".index", "w"); if ($file) { fwrite($file, "File Position\tBinlog_Do_DB\tBinlog_Ignore_DB\n "); fwrite($file, $row->File . "\t" . $row->Position . "\t " . $row->Binlog_Do_DB . "\t" . $row->Binlog_Ignore_DB . "\n"); fclose($file); $a = 1; } } check_errs($a, 0, "Failed to create MySQL Binary log index", "MySQL Binary log index done!"); } break; case "dump": $result = $database . ".sql"; $mysqldump = shell_exec("mysqldump --opt -u " . $username . " -p" . $password . " -h " . $hostname . " -P " . $port . " " . $database); check_errs($mysqldump, null, "Failed to create MySQL dump", "MySQL dump done!"); $file = fopen($result, "w"); $a = 0; if ($file) { fwrite($file, $mysqldump); fclose($file); $a = 1; } check_errs($a, 0, "Failed to save MySQL dump file", "MySQL dump file saved!"); break; default: echo "Choose hotcopy or dump method\n"; if ($lockFilePath) { unlink($lockFilePath); } return 0; } // Rotating files older than n days, all files if 0 if (!$time) { exec("find " . $BASE_PATH . " -name '" . $database . "*.tar.gz'", $find, $return_var); foreach ($find as $one_file) { unlink($one_file); } check_errs($return_var, true, "Failed to rotate files", "Files rotated"); } else { $filter = "-ctime +" . $time; exec("find " . $BASE_PATH . " -name '" . $database . "*.tar.gz' " . $filter, $find, $return_var); foreach ($find as $one_file) { unlink($one_file); } check_errs($return_var, true, "Failed to rotate files", "Files rotated"); } // Compress archive and remove file // // Make the tarball $tarball = $database . "-" . $DATETIME . ".tar.gz"; exec("tar cfz " . $tarball . " " . $result, $tar, $return_var); check_errs($return_var, true, "Failed to create backup tarball", "Tarball packaged!"); // Create a symlink @unlink($database . "-latest.tar.gz"); $res = symlink($tarball, $database . "-latest.tar.gz"); check_errs($res, false, "Failed to create symlink", "Symlink created!"); // Remove temporay files $a = 0; if (is_dir($result)) { if (rrmdir($result)) { $a = 1; } } else { if (unlink($result)) { $a = 1; } } check_errs($a, false, "Failed to clean MySQL files", "MySQL files cleaning done!"); if ($lockFilePath) { unlink($lockFilePath); } // Write into event file if (file_exists($event)) { $fic = fopen($event, "a"); } else { $fic = fopen($event, "w"); } fwrite($fic, "\n#" . date('Y-m-d H:i:s')); fwrite($fic, "\n<strong>" . $database . "</strong> base backup: <strong>" . $method . "</strong> method"); fclose($fic); }
/** * Enable you to configure a server and to write in a XML file * * @param string $file Used configuration file * * @return void */ function configServer($file) { echo exec("clear"); // Check the file check_file($file); // Create a new DOMDocument object $dom = new DOMDocument(); // Load the XML file check_errs($dom->load($file), false, "File " . $file . " not correctly formed.", "File " . $file . " is OK!"); // Write the configuration filename file_put_contents("/tmp/replicationConfigurationFile", $file); // Get the root node $root = $dom->documentElement; echo "\n"; // Get the list of servers already in file $serverList = $dom->getElementsByTagName('serveur'); switch ($serverList->length) { // If no one, nothing case 0: break; // If one, warning and show its name // If one, warning and show its name case 1: $serverNameInFile = $serverList->item(0)->getAttribute('nom'); echo "There is already one server named " . $serverNameInFile . " configurated in this file.\n"; $answer = recup("Do you want to continue (y or n) [default y] ? ", "y"); if ($answer == "n") { echo exec("clear"); menu(); } break; // If more than one, quit // If more than one, quit default: echo exec("clear"); cecho("There is already two servers in this file.", "red"); echo "\n\n"; menu(); } // Get the parameters for the server echo "\n"; announce_script("Server configuration start"); echo "\n"; do { $a = true; $serverName = recup("Give a name to the server (it's for the XML file): "); /* Check for the server name redondancy */ // Get the server from the XML file if ($serverList->length == 1) { foreach ($serverList as $aServer) { if ($aServer->getAttribute('nom') == $serverName) { cecho("This server already exists!", "red"); echo "\n\n"; $a = false; } } } } while (!$a); /* End check */ $firstServer = recup("Is it the \"first\" server (odd primary keys...) (y or n) [default y] ? ", "y"); // Because we will compare with XML if ($firstServer != "n") { $firstServer = "y"; } // If there is already a server in the XML file if ($serverList->length == 1) { foreach ($serverList as $aServer) { if ($aServer->getAttribute('first') == $firstServer) { if ($firstServer == "y") { cecho("This server cannot be first because " . $aServer->getAttribute('nom') . " is already the first!", "red"); echo "\n\n"; cecho("This server will be configured to be the second.", "red"); } else { cecho("This server cannot be second because " . $aServer->getAttribute('nom') . " is already the second!", "red"); echo "\n\n"; cecho("This server will be configured to be the first.", "red"); } } } } $hostname = recup("Server IP: "); $localhost = recup("Is it the localhost address (y or n) [default n] ? ", "n"); // Because we will compare with XML if ($localhost != "y") { $localhost = "n"; } $DBPort = recup("Database port [default 3306]: ", 3306); $DBUser = recup("Database user: "******"Database user password: "******"Replication slave user: "******"Replication slave password: "******"Log-bin file [default /var/log/mysql/bin.log]: ", "/var/log/mysql/bin.log"); $logBinIndex = recup("Log-bin index [default /var/log/mysql/log-bin.index]: ", "/var/log/mysql/log-bin.index"); $logError = recup("Log-error [default /var/log/mysql/error.log]: ", "/var/log/mysql/error.log"); $relayLogFile = recup("Relay-log file [default /var/log/mysql/relay.log]: ", "/var/log/mysql/relay.log"); $relayLogInfoFile = recup("Relay-log info file [default /var/log/mysql/relay-log.info]: ", "/var/log/mysql/relay-log.info"); $relayLogIndex = recup("Relay-log index [default /var/log/mysql/relay-log.index]: ", "/var/log/mysql/relay-log.index"); echo "\n"; info_script("Server configuration end"); echo "\n"; // Create DOMElement and set its attributes $newServer = $dom->createElement('serveur'); $newServer->setAttribute('nom', $serverName); $newServer->setAttribute('first', $firstServer); $newServer->setAttribute('ip', $hostname); $newServer->setAttribute('localhost', $localhost); $newServer->setAttribute('dbport', $DBPort); $newServer->setAttribute('dbusername', $DBUser); $newServer->setAttribute('dbpassword', $DBPassword); $newSlave = $dom->createElement('esclave'); $newSlave->setAttribute('username', $slaveUser); $newSlave->setAttribute('password', $slavePassword); $newLogBin = $dom->createElement('logbin'); $newLogBin->setAttribute('logbinfile', $logBinFile); $newLogBin->setAttribute('logbinindex', $logBinIndex); $newLogBin->setAttribute('logerror', $logError); $newRelayLog = $dom->createElement('relaylog'); $newRelayLog->setAttribute('relaylogfile', $relayLogFile); $newRelayLog->setAttribute('relayloginfofile', $relayLogInfoFile); $newRelayLog->setAttribute('relaylogindex', $relayLogIndex); // Put the nodes into the server node $newServer->appendChild($newSlave); $newServer->appendChild($newLogBin); $newServer->appendChild($newRelayLog); // Put the server node into the root node $root->appendChild($newServer); // Write the XML file check_errs($dom->save($file), false, "Unable to save the " . $file . " file.", "File " . $file . " saved!"); }