.ok{color:#478F47;}.err{color:#DA3833;}.grey{color:grey;}.warn{color:#f0ad4e;}th,td{border-bottom: 1px solid #aaa;}"; // ########## EDIT HERE ################### // ### FTP Data // backup ALL root folders: // if backupAllRootFolders is 1, ftpFoldersToBackup will be ignored and all root folders will be backed up $backupAllRootFolders = 0; // exclude specific root folders from ALL-BACKUP $excludeRootFolders = array(); // specific folder backup: // if backupAllRootFolders is 0, you can specify multiple folders in ftpFoldersToBackup to backup // which root folders should get backed up? comment is optional // format: "foldername___comment" // or: "foldername" $ftpFoldersToBackup = array("ordner1", "ordner2", "ordner3"); // exclude files or folders - you should keep these four entries and add your stuff $ignoreMore = array("*.sql.gz", "*.tar.gz", "usage", "logs"); // ### FTP Export $copyToExternalFtp = 0; // copy new backup files to external ftp server? should be 1/"yes"/"ja" or 0/"no"/"nein" // external (ftp) servers to copy new backups to, format: // in general: ftp://username:password@url:port/path (port is required!) // ftp://user:pw@ftp.server.com:21/ // ftp://user:pw@serverurl.com:21/optional/path // $externalFtpUri = "ftp://admin:password@barketing.dns.com:21/Data/FTP-Backups"; // ### MySQL Data $backupMysqlData = 0; // one or more databases of the local mysql server to backup, multiple data combined with "___", comment is optional // format: "dbName___dbUser___dbPassword___comment" // or: "dbName___dbUser___dbPassword" $databasesToBackup = array(); // ### Mailing Data $sendMail = 1; // send notification mail when all backups are done - should be 1/"yes"/"ja" or 0/"no"/"nein" $mailTo = "admin@backup.com"; // valid mail address to send the mail to $mailSubject = "Automatische FTP Sicherung abgeschlossen"; // mail subject // additional mail annotations that gets inserted after the main mail content $mailAdditionalNotes = "Hiermit kann - wenn gewünscht - zusätzlicher Text in die Mail eingebaut werden."; $mailBackupDetails = 0; // send information about successful backup files? should be 1/"yes"/"ja" or 0/"no"/"nein" // ### General Options $backupFileMaximum = 1; // how many archives should be stored? $dir = $pfad."backup/"; // in which subfolder is this backup php file? this would be: "root/backup/" // ######### STOP EDITING HERE ################### echo "".date("d.m.Y G:i:s")."

"; $allTime = time(); echo "_________________ FTP __________________"; // ################### // ### FTP BACKUPS ### // ################### if ($backupAllRootFolders==1) { $ftpFoldersToBackup = array_filter(glob($pfad."*", GLOB_ONLYDIR)); $ftpFoldersToBackup = preg_replace('/(\/www\/htdocs\/\w+\/)/', '', $ftpFoldersToBackup); if (isset($excludeRootFolders)) $ftpFoldersToBackup = array_diff($ftpFoldersToBackup, $excludeRootFolders); } foreach ($ftpFoldersToBackup as $folderData) { // get data from folder string by splitting at "___" $arrThisJobData = explode("___", $folderData, 2); // check for minimal size of 1: folderName if(count($arrThisJobData)>=1) { $folder = $arrThisJobData[0]; // optional: comment - could be empty if(empty($arrThisJobData[1])) { $folderComment = ""; } else { $folderComment = $arrThisJobData[1]; } $ftpJobTime = time(); echo "
########################################
"; echo "Verzeichnis $folder wird gesichert...
"; flush(); // check if folder exists if(!file_exists($pfad.$folder)) { echo "Sicherung fehlgeschlagen. Zu sichernder Ordner $pfad$folder existiert nicht."; continue; } // Name: [verzeichnis]_[Datum]_[Uhrzeit].tar.gz $archivName = "FTP_$folder".date('_Y-m-d_His').".tar.gz"; // Name: [All-Inkl-Accountname]_[Datum]_[Uhrzeit].tar.gz //$archivName = preg_replace('/.+\/(.+)\/$/', '$1', $pfad).date('_Y-m-d_His').".tar.gz"; // ######### create backup $archiveObject = new Archive_Tar($archivName, true); $archiveObject->setIgnoreList($ignoreMore); $archiveObject->createModify($pfad.$folder, "", $pfad); // process backup $archivePath = $dir.$archivName; $archivSize = round(filesize($archivePath)/1000000, 1); // check created archive if(!validateBackup($archivePath)) { // abort process due to wrong type or too small filesize (which likely is an error) echo "Verzeichnis-Sicherung fehlgeschlagen. Erstelltes Archiv ist fehlerhaft.
"; // debug echo "

Debug:
"; echo "Pfad: $archivePath
"; echo "Typ: ".gettype($archivePath)."
"; echo "Größe: $archivSize MB

"; continue; } else { $backupTime = time() - $ftpJobTime; if (is_int($backupTime)) { echo "Backup fertig: $archivName (Größe: $archivSize MB, Dauer: $backupTime Sekunden)
"; } else { echo "Backup fertig: $archivName
"; } $newFtpBackups[$archivName] = $archivSize." MB"; array_push($backupinfo, array($folder, $archivName, $archivSize." MB", $backupTime." Sekunden", date("d.m.Y G:i:s"), $folderComment)); } // ########## delete backups if too many echo "Aufräumen der FTP Backups...
"; cleanBackups("FTP", $folder, $dir, "gz"); // close job $ftpBackupEndTime = time() - $ftpJobTime; echo "Backup für Verzeichnis $folder abgeschlossen.
"; if (is_int($ftpBackupEndTime)) { echo "######################################## (Dauer: $ftpBackupEndTime Sekunden)
"; } else { echo "########################################
"; } flush(); } else { echo "Angabe der Verzeichnis Daten fehlerhaft."; echo "

Debug:
"; echo "Verzeichnis Name: $arrThisJobData[0]
"; echo "Verzeichnis Comment: $arrThisJobData[1]
"; } } // ########## echo backup summary and add it to mailtext backupSummary($newFtpBackups); flush(); echo "________________ MySQL ________________"; // ################### // ### SQL BACKUPS ### // ################### if (!isset($backupMysqlData) || $backupMysqlData== 0 && in_array($backupMysqlData, array("no", "nein"))) { echo "MySQL Datenbanken werden nicht gesichert. Option ist deaktiviert.
"; } else { if(isset($databasesToBackup)&&count($databasesToBackup)>=1) { foreach ($databasesToBackup as $databaseData) { $sqlJobTime = time(); // get data from database string by splitting at "___" $arrThisJobData = explode("___", $databaseData, 4); // check for minimal size of 3: dbName, dbUser, dbPassword if(count($arrThisJobData)>=3) { $dbName = $arrThisJobData[0]; $dbUser = $arrThisJobData[1]; $dbPassword = $arrThisJobData[2]; // optional: comment - could be empty if(empty($arrThisJobData[3])) { $dbComment = ""; } else { $dbComment = $arrThisJobData[3]; } echo "
########################################
"; echo "Datenbank $dbName wird gesichert...
"; flush(); $sqlFile = "DB_$dbName".date('_Y-m-d_His').".sql"; exec("mysqldump -u '$dbUser' -p'$dbPassword' --quick --allow-keywords --add-drop-table --complete-insert --quote-names '$dbName' >$sqlFile"); exec("gzip $sqlFile"); $sqlFilePath = $dir.$sqlFile.".gz"; $sqlSize = round(filesize($sqlFilePath)/1000000, 1); if(!validateBackup($sqlFilePath)) { // wrong type or too small filesize (which likely is an error) echo "Datenbank-Sicherung fehlgeschlagen. Erstellter Export ist fehlerhaft.
"; // debug echo "

Debug:
"; echo "Datenbank Name: $dbName
"; echo "User: $dbUser
"; echo "Passwort: $dbPassword
"; echo "Kommentar: $dbComment
"; echo "Pfad: $sqlFilePath
"; echo "Typ: ".gettype($sqlFilePath)."
"; echo "Größe: $sqlSize MB

"; } else { $backupTime = time() - $sqlJobTime; if (is_int($backupTime)) { echo "Backup fertig: $sqlFile (Größe: $sqlSize MB, Dauer: $backupTime Sekunden)
"; } else { echo "Backup fertig: $sqlFile
"; } $newSqlBackups[$sqlFile.".gz"] = $sqlSize." MB"; array_push($backupinfo, array($dbName, $sqlFile, $sqlSize." MB", $backupTime." Sekunden", date("d.m.Y G:i:s"), $dbComment)); } // ########## delete DB backups if too many echo "Aufräumen der DB Backups...
"; cleanBackups("DB", $dbName, $dir, "gz"); $sqlJobEndTime = time() - $sqlJobTime; echo "Backup für Datenbank $dbName abgeschlossen.
"; if (is_int($sqlJobEndTime)) { echo "######################################## (Dauer: $sqlJobEndTime Sekunden)
"; } else { echo "########################################
"; } flush(); } else { echo "Angabe der DB Daten fehlerhaft."; echo "

Debug:
"; echo "DB Name: $arrThisJobData[0]
"; echo "DB User: $arrThisJobData[1]
"; echo "DB PW: $arrThisJobData[2]
"; echo "DB Comment: $arrThisJobData[3]


"; } } // foreach } // if } // ########## echo backup summary and add it to mailtext backupSummary($newSqlBackups); flush(); echo "________________ Export _________________"; // ######################## // ### COPY TO EXTERNAL ### // ######################## if (!isset($copyToExternalFtp) || $copyToExternalFtp== 0 && in_array($copyToExternalFtp, array("no", "nein"))) { echo "Backups werden nicht auf einen externen FTP kopiert. Option ist deaktiviert.
"; } else { $ftpTime = time(); echo "
########################################
"; // get a ftp connection resource $ftpCon = getFtpConnectionByURI($externalFtpUri); flush(); // ########## copy all FTP backups to external FTP copyBackupsToFtp($newFtpBackups, "FTP", $ftpCon); flush(); // ########## copy all DB/SQL backups to external FTP copyBackupsToFtp($newSqlBackups, "DB", $ftpCon); flush(); ftp_close($ftpCon); $ftpExternalEndTime = time() - $ftpTime; array_push($backupinfo, array("Export -> external FTP", count($newSqlBackups) + count($newFtpBackups) . " Sicherungen", "", $ftpExternalEndTime." Sekunden", date("d.m.Y G:i:s"), "")); if (is_int($ftpTime)) { echo "######################################## (Dauer: $ftpExternalEndTime Sekunden)
"; } else { echo "########################################
"; } } flush(); // ################### // ### PRINT INFOS ### // ################### echo "
_____________ Zusammenfassung _____________"; $backupDetailsText = backupDetails($backupinfo); echo $backupDetailsText; // ################# // ### SEND MAIL ### // ################# if (!isset($sendMail) || $sendMail== 0 && in_array($sendMail, array("no", "nein"))) { echo "
Benachrichtigungsmail wurde nicht verschickt. Option ist deaktiviert.
"; } else { if(!preg_match( '/^([a-zA-Z0-9])+([.a-zA-Z0-9_-])*@([a-zA-Z0-9_-])+(.[a-zA-Z0-9_-]+)+/' , $mailTo)) { echo "
FEHLER: Mail konnte nicht versendet werden, da die Empfängeradresse ungültig ist!
"; } else { if (empty($mailSubject)) $mailSubject = "Automatische FTP Sicherung abgeschlossen"; // add backup informations as table to mailtext if (!isset($mailBackupDetails) || $mailBackupDetails== 0 && in_array($mailBackupDetails, array("no", "nein"))) { // do not append information about backups } else { $mailText = backupDetails($backupinfo); } if (!empty($mailAdditionalNotes)) $mailText .= "
Anmerkungen:
".$mailAdditionalNotes; mail( $mailTo, $mailSubject, $mailText, "From: backupscript@all-inkl-backup.de\r\n" . "Reply-To: backupscript@all-inkl-backup.de\r\n" . "Content-Type: text/html\r\n" ) or die("
FEHLER: Mail konnte wegen eines unbekannten Fehlers nicht versendet werden.
"); echo "
Benachrichtigungsmail wurde erfolgreich verschickt!
"; } } flush(); function backupDetails($backups) { global $allTime; $columnDefinition = array("Ordner/DB-Name", "Dateiname", "Größe", "Dauer", "Timestamp", "Kommentar"); $backupDetailsText = "
"; for($d=0;$d"; } $backupDetailsText .= ""; for($i=0;$i"; } $backupDetailsText .= ""; } $backupDetailsText .= "
"; $allEndTime = time() - $allTime; if (is_int($allEndTime)) { $backupDetailsText .= "Gesamtbackupzeit: $allEndTime Sekunden
"; } return $backupDetailsText; } function validateBackup($filePath) { if(!file_exists($filePath)) { echo "Fehler bei der Backup Überprüfung. Die Backup-Datei ist fehlerhaft oder nicht vorhanden.
"; return false; } if (!is_numeric(filesize($filePath))) { echo "Fehler bei der Backup Überprüfung. Die Größe der Backup-Datei ist fehlerhaft.
"; return false; } $backupFullSize = filesize($filePath); // check created dump if (!is_file($filePath)==1 || !$backupFullSize>50) { echo "Fehler bei der Backup Überprüfung. Die Backup-Datei ist fehlerhaft.
"; return false; } else { return true; } } function cleanBackups($dataTypeIdentifier, $nameIdentifier, $dir, $fileType) { global $backupFileMaximum; flush(); // integer starts at 0 before counting $i = 0; $backupFiles = array(); // ######### collect valid backup files if ($handle = opendir($dir)) { while (($file = readdir($handle)) !== false) { if (is_int(strpos($file, $dataTypeIdentifier."_".$nameIdentifier)) == true && pathinfo($file)["extension"] == $fileType && !in_array($file, array('.', '..')) && !is_dir($dir.$file) ) { $backupFiles[$dir.$file] = filectime($dir.$file); } } } echo count($backupFiles)." valide Backups dieses Ordners gefunden, "; echo "$backupFileMaximum Backups sollen behalten werden. "; if (count($backupFiles)-$backupFileMaximum>0) { echo count($backupFiles)-$backupFileMaximum; } else { echo "0"; } echo " Backups werden gelöscht:
"; flush(); // ######### sort and delete oldest backups // sort backup files by date arsort($backupFiles); // reset counter variable $i = 0; // delete oldest files foreach ($backupFiles as $filePath => $value) { if($i>=$backupFileMaximum) { echo "$filePath wird gelöscht...
"; if (unlink($filePath)) { echo "Datei erfolgreich gelöscht.
"; } else { echo "Fehler beim Löschen der Datei.
"; } } $i++; } flush(); } function backupSummary($backupFiles) { global $allTime; global $mailText; $backupTime = time() - $allTime; if(count($backupFiles)>0) { echo "
Die automatische Sicherung hat ".count($backupFiles)." Datensätze (Verzeichnisse/Datenbanken) in insgesamt $backupTime Sekunden gesichert.

"; $mailText .= "
Die automatische Sicherung hat ".count($backupFiles)." Datensätze (Verzeichnisse/Datenbanken) in insgesamt $backupTime Sekunden gesichert.

"; } else { echo "
Es scheint leider so als wenn keine Backups erfolgreich erstellt wurden.

"; $mailText .= "
Es scheint leider so als wenn keine Backups erfolgreich erstellt wurden.

"; } } // function to get ftp connection object from URI // basics were from: http://php.net/manual/de/function.ftp-connect.php#89811 function getFtpConnectionByURI($uri) { // Split FTP URI into: // $match[0] = ftp://admin:password@barketing.dns.com:21/Data/FTP-Backups // $match[1] = ftp // $match[2] = admin // $match[3] = password // $match[4] = barketing.dns.com // $match[5] = 21 // $match[6] = /Data/FTP-Backups preg_match("/([a-z]*?):\/\/(.*?):(.*?)@(.*?):(.*?)(\/.*)/i", $uri, $match); $ftpCon = null; // check if port is set and uri is formatted correctly if(is_int(intval($match[5]))) { $port = intval($match[5]); // check if ftp(s) or sftp is chosen if($match[1]=="ftp") { // set up and ftp(s) connection, login echo "Stelle (FTPs über SSL - Port $port) Verbindung zu FTP Server $match[4] her...
"; // try ftps over ssl, usally through port 21 $ftpCon = ftp_ssl_connect($match[4], $port, 30); if (!gettype($ftpCon)=="resource") { echo "FTP über SSL - Port $port - Verbindung fehlgeschlagen!
"; echo "Stelle (unsicheres FTP - Port $port) Verbindung zu FTP Server $match[4] her...
"; // try normal insecure ftp $ftpCon = ftp_connect($match[4], $port, 30); } if (gettype($ftpCon)=="resource") { $login = ftp_login($ftpCon, $match[2], $match[3]); $pasv = ftp_pasv($ftpCon, true); } } else if($match[1]=="sftp") { echo "SFTP Unterstützung noch nicht implementiert.
"; // if(!$port==22) { // echo "SFTP Übertragung aber Port ist nicht 22. Ist der gewählte Port $port korrekt?
"; // } // echo "Stelle (sichere sFTP - Port $port) Verbindung zu FTP Server $match[4]$match[5]:$match[6] her...
"; // $ftpCon = ssh2_connect($match[4], $port, 30); // ssh2_auth_password($ftpCon, $match[2], $match[3]); // $sftp = ssh2_sftp($ftpCon); } else { echo "Kein gültiger Verbindungstyp (ftp/sftp) angegeben.
"; } } else { echo "Der Port ist fehlerhaft angegeben. Bitte URI prüfen.
"; } if ($ftpCon && gettype($ftpCon)=="resource") { echo "Verbindung hergestellt"; if ($login) { echo ", Login erfolgreich"; if ($pasv) { echo ", passiver Modus aktiviert"; if(!isset($match[6]) || $match[6] == "") { echo ".
"; return $ftpCon; } else if (ftp_chdir($ftpCon, $match[6])) { echo ", Verzeichniswechsel zu $match[6] erfolgreich.
"; return $ftpCon; } else { echo ", Verzeichniswechsel zu $match[6] fehlerhaft.
"; return null; } } else { echo ", passiver Modus konnte nicht aktiviert werden. Upload wird trotzdem probiert.
"; return $ftpCon; } } else { echo ", Login fehlgeschlagen.
"; return null; } } echo "Fehler beim Verbinden mit dem FTP Server $match[4]$match[5]$match[6].
"; echo "

Debug:
"; echo "URI (komplett): $match[0]
"; echo "Typ: $match[1]
"; echo "URI ohne Typ: $match[4]
"; echo "Username: $match[2]
"; echo "Passwort: $match[3]
"; echo "Port: $match[5]
"; echo "Unterordner: $match[6]
"; echo "

"; // Or retun null return null; } function copyBackupsToFtp($backupFiles, $backupType, $ftpCon) { if(empty($backupFiles)) { "
Es scheint leider so als wenn keine $backupType Backups erfolgreich erstellt wurden.

"; } else { echo "".count($backupFiles)." $backupType Backups werden auf externen FTP kopiert...
"; if(gettype($ftpCon)=="resource") { foreach ($backupFiles as $fileName => $fileSize) { $uploadTime = time(); echo "Kopiere $fileName (Größe: $fileSize MB) auf den FTP...
"; flush(); if (ftp_put($ftpCon, $fileName, $fileName, FTP_ASCII)) { $uploadEndTime = time() - $uploadTime; if (is_int($uploadEndTime)) { echo "Backup erfolgreich kopiert. (Dauer: $uploadEndTime Sekunden)
"; } else { echo "Backup erfolgreich kopiert.
"; } } else { echo "Fehler beim Kopieren des Backups.
"; continue; } flush(); } } } } // from: http://stackoverflow.com/a/20147885/516047 function debug_to_console($data) { if (is_array($data)) { $output = ""; } else { $output = ""; } echo $output; } // from: http://stackoverflow.com/a/10473026/516047 function startsWith($haystack, $needle) { // search backwards starting from haystack length characters from the end return $needle === "" || strrpos($haystack, $needle, -strlen($haystack)) !== FALSE; } ?>