MySQL-Datenbanken Importieren und Exportieren per PHP-Skript

Wer in seinem Tarif keinen SSH-Zugang hat muss sich bei MySQL-Sicherungen entweder mit dem PHPmyAdmin (der ab einer Datenbankgröße von wenigern MB ohnehin ganz aufgibt) rumärgern oder er greift zum Import per Skript.

Folgende Skripte dienen zum Export und Import von MySQL Datenbanken. Der Datenbank Dump wird hier nicht gepackt, bzw. es wird erwartet dass er ungepackt vorliegt.
Eventuelle Fehlermeldungen werden über das Skript ausgegeben.

Hier das Import-Skript. Wichtig ist, dass die Werte für Hostname, Datenbankname, Benutzername, passwort und Name des MySQL-Dumps am Anfang angepasst werden an die Daten der jeweiligen MySQL-Datenbank ($HOSTNAME, $MYSQL_PASSWORD, $MYSQL_USER, $MYSQL_DATABASENAME, $DUMPFILENAME).

Das Skript wird dann ganz normal über den Browser aufgerufen (http://domain.tld/import.php).

Import-Skript:

<?php

//Hostname/Servername des Datenbankservers
$HOSTNAME = "db1234567.db.1and1.com";

//Passwort für die MySQL-Datenbank in die importiert wird
$MYSQL_PASSWORD = "XYZ";

//Benutzername der MySQL-Datenbank in die importiert wird
$MYSQL_USER = "dbo1234567";

//Datenbankname der MySQL-Datenbank in die importiert wird
$MYSQL_DATABASENAME = "db1234567";

//Name der Datei die importiert werden soll. Der Dump darf nicht gepackt sein.
$DUMPFILENAME = "dump.sql";

 

$cmd = "/usr/bin/mysql --host=".$HOSTNAME." --password=".$MYSQL_PASSWORD." --user=".$MYSQL_USER." ".$MYSQL_DATABASENAME." < ".$DUMPFILENAME;

echo "<html>\n<head>\n<title>MySQL-Import</title>\n</head>\n<body style='background-color:#FDF8CE;'>\n";
echo "<span style='font-family:tahoma,geneva,sans-serif;'>\n";

echo "<h1><strong>MySQL Import-Skript</strong></h1>\n";

echo "<hr/>\n";
echo "<b>Ausgeführter Befehl:</b><br>";
echo $cmd."<br><br>";
echo "<hr/>\n";

          $proc=proc_open($cmd, array(0=>array('pipe', 'r'), 1=>array('pipe', 'w'), 2=>array('pipe', 'w')), $pipes);
          fwrite($pipes[0], '');fclose($pipes[0]);
          $stdout=stream_get_contents($pipes[1]);fclose($pipes[1]);
          $stderr=stream_get_contents($pipes[2]);fclose($pipes[2]);
          $rtn=proc_close($proc);
          echo "<b>Errors:</b> ".$stderr."<br><br>\n";
          echo "<b>Output:</b> ".$stdout."<br><br>\n";
          echo "<b>Returns:</b> ".$rtn."<br><br>\n";

echo "<hr/>\n";
echo "</span><br>\n";
echo "<strong><span style='font-size:10px;'><span style='font-family: tahoma,geneva,sans-serif;'><a style='text-decoration: none' href='https://sinnfragen.mzimmer.com/'>Bow Ties are cool</a></span></span></strong>\n";
echo "</body>\n</html>\n";

 

?>

 

Export-Skript:

<?php

//Hostname/Servername des Datenbankservers
$HOSTNAME = "db1234567.db.1and1.com";

//Passwort für die MySQL-Datenbank in die exportiert wird
$MYSQL_PASSWORD = "XYZ";

//Benutzername der MySQL-Datenbank in die exportiert wird
$MYSQL_USER = "dbo1234567";

//Datenbankname der MySQL-Datenbank in die exportiert wird
$MYSQL_DATABASENAME = "db1234567";

//Name der Datei in die exportiert werden soll.
$DUMPFILENAME = "dump.sql";

$cmd = "/usr/bin/mysqldump --host=".$HOSTNAME." --password=".$MYSQL_PASSWORD." --user=".$MYSQL_USER." ".$MYSQL_DATABASENAME." > ".$DUMPFILENAME;

echo "<html>\n<head>\n<title>MySQL-Export</title>\n</head>\n<body style='background-color:#D5FDCE;'>\n";
echo "<span style='font-family:tahoma,geneva,sans-serif;'>\n";

echo "<h1><strong>MySQL Export-Skript</strong></h1>\n";

echo "<hr/>\n";
echo "<b>Ausgeführter Befehl:</b><br>";
echo $cmd."<br><br>";
echo "<hr/>\n";

          $proc=proc_open($cmd, array(0=>array('pipe', 'r'), 1=>array('pipe', 'w'), 2=>array('pipe', 'w')), $pipes);
          fwrite($pipes[0], '');fclose($pipes[0]);
          $stdout=stream_get_contents($pipes[1]);fclose($pipes[1]);
          $stderr=stream_get_contents($pipes[2]);fclose($pipes[2]);
          $rtn=proc_close($proc);
          echo "<b>Errors:</b> ".$stderr."<br><br>\n";
          echo "<b>Output:</b> ".$stdout."<br><br>\n";
          echo "<b>Returns:</b> ".$rtn."<br><br>\n";

echo "<hr/>\n";
echo "</span><br>\n";
echo "<strong><span style='font-size:10px;'><span style='font-family: tahoma,geneva,sans-serif;'><a style='text-decoration: none' href='https://sinnfragen.mzimmer.com/'>Bow Ties are cool</a></span></span></strong>\n";
echo "</body>\n</html>\n";

?>

 

Domain immer über HTTPS aufrufen

Bei der Bestellung eines SSL-Zertifikats muss man sich entscheiden auf welche Domain oder Subdomain man es bestellen will.
Für viele Leute gehört das „www.“ zwingend zu der Domain dazu, obwohl es eigentlich nur eine Subdomain ist.

Nehmen wir an, wir haben eine Domain „meinedomain.de“ auf die das SSL-Zertifikat eingerichtet ist.
Der gültige Aufruf per HTTPS sähe so aus: https://meinedomain.de
Würde jemand im Browser nur meinedomain.de oder www.meinedomain.de aufrufen, oder auch über den Link einer Suchmaschine die Seite aufrufen, würde die Seite unverschlüsselt aufgerufen werden.

Über eine .htaccess mit Rewrite Rules kann man den Besucher direkt auf die Variante mit Verschlüsselung führen.

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^meinedomain.de$ [NC]
RewriteRule ^(.*)$ https://meinedomain.de/$1 [R=301,L]

Würde jemand gezielt https://www.meinedomain.de aufrufen, bekäme er von seinem Browser natürlich dennoch eine Sicherheitswarnung durch den Browser. Erst wenn er die Seite dennoch aufrufen würde, hätte der Redirect eine Chance zu greifen.

Der umgekehrte Weg (das SSL-Zertifikat wurde auf www.meinedomain.de bestellt) sähe so aus:

RewriteEngine On
RewriteBase /
RewriteCond %{HTTP_HOST} !^www.meinedomain.de$ [NC]
RewriteRule ^(.*)$ https://www.meinedomain.de/$1 [R=301,L]

Backups per Cronjob

Wer in seinem 1&1 Webhosting-Vertrag SSH-Zugang hat, kann Cronjobs anlegen. Darüber lassen sich z.B. zeitgesteuerte Sicherungen anlegen von Webspace und MySQL-Datenbank.

Dazu werden die Sicherungen als Archiv gepackt und mit einem Dateinamen versehen der das Datum enthält.
Eine Sicherung vom 31.12.2012 würde z.B. dann backup2012_12_31.sql.gz heissen.

Beispiel für ein Skript (mysqlbackup.sh), die Dateirechte sollten auf 744 stehen:

#!/usr/bin/perl

########### Konfiguration ###########
#Pfad in den das endgültige Backup abgelegt werden soll
$PATH = „/homepages/5/d1234567/htdocs/backup/“;

#Host/Servername der MySQL
$HOST = „db1976.1und1.de“;

#Passwort der MySQL
$PASS = „geheim“;

#Benutzername der MySQL
$USER = „dbo1234567“;

#Datenbankname
$DB = „db1234567“;

#Dateiname der erstellten Sicherung. Dieser wird durch Datum und .sql.gz ergänzt
#aus mysqlbackup wird z.B. mysqlbackup2012_12_31.sql.gz
$BACKUPNAME = „mysqlbackup“;
#Temporärer Pfad in dem der Dump erstellt wird bevor er dann gepackt und umbenannt/verschoben wird
$TEMPPATH = „/homepages/5/d210846470/htdocs/“;

########### ######## ###########

#Dump der MySQL erstellen und erstmal als dump.sql ins htdocs legen
system(„/usr/bin/mysqldump –host=“.$HOST.“ –password=“.$PASS.“ –user=“.$USER.“ „.$DB.“ > „.$TEMPPATH.“dump.sql“);

#Datum ermitteln
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
#Datum formatieren
$DATE = (1900 + $year).“_“.($mon + 1).“_“.$mday;

#Dump packen
system(„gzip „.$TEMPPATH.“dump.sql“);

#gepackten Dump verschieben/umbenennen
system(„mv „.$TEMPPATH.“dump.sql.gz „.$PATH.$BACKUPNAME.$DATE.“.sql.gz“)

Ähnliches kann man auch mit einem Verzeichnis auf dem Webspace machen. Im Prinzip wird nur der enstrechende Ordner als Archiv in den Backup-Ordner gelegt.
Eine Sicherung vom 31.12.2012 würde in dem Beispiel dann wordpressblog_2012_12_31.tar heissen.

Beispiel für ein Skript (webspacebackup.sh), die Dateirechte sollten auf 744 stehen:

#!/usr/bin/perl

#Pfad des ordners der gesichert werden soll
$WEBSITEPATH = „/homepages/5/d1234567/htdocs/wordpress/“;

#Pfad in den das endgültige Backup abgelegt werden soll
$BACKUPPATH = „/homepages/5/d1234567/htdocs/backup/“;

#Name der Backupdatei, Datum und .tar werden zugefügt später
$BACKUPNAME = „wordpressblog_“;

#Aktuelles Datum bestimmen und formatieren
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
$DATE = (1900 + $year).“_“.($mon + 1).“_“.$mday;

#Dateien packen
system („tar -cvvf „.$BACKUPPATH.$BACKUPNAME.$DATE.“.tar „.$WEBSITEPATH);

Die Sicherung der Datenbank wird in dem Fall immer Montags um 10:30 veranlasst, die für das Verzeichnis um 11:30. Die Skripte für die Sicherungen liegen dabei in einem eigenen Verzeichnis.
Der dritte Cronjob löscht im Verzeichnis, in dem die Sicherungen liegen, alle Dateien die älter als 30 Tage sind, damit der Webspace nicht total voll läuft. Das Skript sollte nicht in dem Verzeichnis der Sicherungen liegen, da es sich ansonsten nach 30 Tagen selbst löschen würde.
Das MAILTO bewirkt dass eine E-Mail bei Ausführung eines Cronjobs versendet wird. Dies ist auch zum debuggen von Cronjobs interessant.
Das „2>&1“ ist eine Umleitung der Ausgabe. Es gibt STDIN, STDOUT, and STDERR die nummeriert sind mit 0, 1 und 2. Falls es Fehler gibt, landen diese Informationen in der Mail die versendet wird.


MAILTO='[email protected]'
30 10 * * 5 /homepages/5/d1234567/htdocs/cron/mysqlbackup.sh 2>&1
30 11 * * 5 /homepages/5/d1234567/htdocs/cron/webspacebackup.sh 2>&1
50 11 * * 5 find /homepages/5/d1234567/htdocs/backup/ -mtime +30 -exec rm {} \;

Nur eine php.ini dank Symlinks

Update: Mit den PHP-Versionen 5.4 und höher gibt es einen einfacheren und eleganteren Weg. Dieser lässt sich aber auch nicht immer einsetzen. Für Zend, ionCube oder OpCache ist z.B. eine php.ini notwendig

Die php.ini wirkt immer nur auf das Verzeichnis, in dem sie sich befindert (anders als die .htaccess).

Falls man Shell-Zugang (SSH) hat und sichergehen will, dass der Verweis in jedem Unterverzeichnis ist, kann man sich mit folgendem Befehl Symlinks erstellen lassen. Änderungen an der Datei werden dadurch auch in allen(!) Verzeichnissen aktiv, da der Symlink nur ein Verweis auf die Datei ist.

find -type d -exec ln -sv /homepages/24/d1234567/htdocs/php.ini {}/php.ini \;

Der Pfad („/homepages/24/d1234567/htdocs/„) muss natürlich angepasst werden.

Die Symlinks können mit folgendem Befehl entfernt werden:
find -name "php.ini" -links 1 -exec rm -i {} \;
Dieser fragt für jeden Eintrag nach, ob er entfernt werden soll. Will man das nicht, lässt man den -i Parameter weg.
Achtung! Der Befehl beschränkt sich nicht auf Symlinks sondern entfernt ggf. auch die originale php.ini also Vorsicht hier.

GZIP-Kompression aktivieren

Wer bei 1&1 im Shared Webosting (Linux) die GZIP-Kompression für seine Website anstellen will, kann dies über eine eigene php.ini machen. Dies ist eine simple Textdatei, die einfach nur php.ini heissen muss.

Anders als eine .htaccess wirkt die php.ini immer nur auf das Verzeichnis, in dem sie liegt. Gerade wenn die Skripte auf mehrere Verzeichnisse verstreut sind, muss die Datei auch in mehren Verzeichnissen liegen.

Folgende Zeile fügt man in der php.ini dafür ein:
zlib.output_compression = on

Ob es funktioniert hat, kann man auf diversen Seiten wir beim Gidnetwork testen.

Wie man über Symlinks nur eine php.ini nutzen kann, ist hier beschrieben.