Automatisches Backup für All-Inkl Webspace

Posted on Mai 1, 2013 in PHP, Webentwicklung | 7 Comments
Automatisches Backup für All-Inkl Webspace

Seit vielen Jahren habe ich meine ganzen Webgeschichten bei All-Inkl gehostet. Ich bin mit dem Anbieter ganz zufrieden. Die Server sind sehr zuverlässig, die Administrationsoberfläche ist durchdacht, der Support antwortet innerhalb von 15 Minuten und alle Funktionen und Extensions, die man so braucht, sind vorhanden. Eines fehlt aber: Eine einfache Möglichkeit Backups zu erstellen.

Mittlerweile hat sich so einiges bei meinem Webhoster angesammelt. Mein Anspruch ist es also, je nach Projekt ein Backup erstellen zu können. Sprich Verzeichnis XYZ und die dazugehörige MySQL Datenbank schön abgepackt als ZIP File, so dass ich die nur noch herunterladen und auf meinen Rechner archivieren muss. All-Inkl bietet zwar in ihren FAQs schon einige interessante Ansätze, aber entweder es betrifft nur den Backup einer MySQL Datenbank, oder man braucht gleich einen der Managed-Server Tarife.

Also habe ich selbst ein kleines Skript geschrieben, dass ein Backup erzeugt. Wichtig: Es funktioniert nur mit dem All-Inkl Premium Tarif, denn das Skript verwendet SSH und das gibt es erst ab den Premium Tarif. Eine Variante, bei der alleine mit PHP Bordmittel ein Backup durchgeführt wird, scheitert leider am begrenzten Speicher. All-Inkl gesteht PHP nur 64MB Arbeitsspeicher zu. Erstellt man also ein Backup für ein Verzeichnis und packt dieses in eine ZIP Datei, so ist bei 64MB Schluss und es kommt ein memory limit exceeded.

Nun aber zu meiner Lösung. Ich verwendet den SSH Zugang, führe damit ein mysqldump aus und packe alles mit tar in eine tar.gz Datei ein. Nachdem All-Inkl die SSH Extension von PHP nicht zur Verfügung stellt, verwende ich die phpseclib. Diese hervorragende Bibliothek rund um das Thema Verschlüsselung bietet einen rein PHP basierten SSH Client an. Die Verwendung des SSH Clients ist denkbar einfach:

<?php
include('Net/SSH2.php');
$ssh = new Net_SSH2('www.domain.tld');
if (!$ssh->login('username', 'password')) {
exit('Login Failed');
}
echo $ssh->exec('pwd');
echo $ssh->exec('ls -la');
?>

Über die phpseclib habe ich bereits an anderer Stelle schon einmal etwas geschrieben.

Nun aber zum Backup-Skript, dass wie folgt aussieht:

<?PHP
$sshUser = 'youruser';
$sshPassword = 'yourpass';
$sshHost = 'yourhost';
$base = "/www/htdocs/<ftpuser>/";
$backupDir = "backup/";
$dbs = array(
array(
"name"   => "wordpress",
"dbname" => "d1234567",
"passwd" => "secret",
"dir"    => "wordpress"
),
array(
"name"   => "website",
"dbname" => "d321",
"passwd" => "secret",
"dir"    => "website/www"
),
array(
"name"   => "selfoss",
"dir"    => "website/selfoss"
),
array(
"name"   => "database123",
"dbname" => "d987324",
"passwd" => "secret",
)
);
// ssh connection
include('Net/SSH2.php');
$ssh = new Net_SSH2($sshHost);
if(!$ssh->login($sshUser, $sshPassword))
die('ssh login failed');
$baseWithoutTrailingSlash = substr($base, 1);
foreach($dbs as $db) {
echo $db["name"] . "<br />";
ob_flush();
// directory for backup
$dir = "";
if(isset($db["dir"]) && strlen(trim($db["dir"]))>0) {
$dir = $baseWithoutTrailingSlash . $db["dir"];
}
// backup database
$sql = "";
if(isset($db["dbname"]) && strlen(trim($db["dbname"]))>0) {
$db_name = $db["dbname"];
$db_passwd = $db["passwd"];
$sql_file = $db["name"] . "_" . date('Y.m.d') . ".sql";
$sql = $baseWithoutTrailingSlash . $backupDir . $sql_file;
echo $ssh->exec("mysqldump -u " . $db_name . " -p'" . $db_passwd . "' --allow-keywords --add-drop-table --complete-insert --quote-names " . $db_name . " > " . $base . $backupDir . $sql_file);
}
// generate tar.gz file
$tar_file = $base . $backupDir . $db["name"] . "_" . date('Y.m.d') . ".tar.gz";
$result = $ssh->exec("tar cfz " . $tar_file . " -C / " . $dir . " " . $sql);
if(strlen(trim($result))>0)
echo $result . "<br />\n";
// delete temporarily database dump
if(strlen($sql)>0 && strlen(trim($base))>4 && strlen(trim($sql_file))>4)
echo $ssh->exec("rm " . $base . $backupDir . $sql_file);
}
echo "finished";

Über die Variablen $sshUser, $sshPassword und $sshHost wird der SSH Benutzer und Host festgelegt. $base ist der Basispfad eurer Installation. Bei All-Inkl ist das immer /www/htdocs/<ftp-username>/. Das Verzeichnis in $backupDir gibt an, wo das Backupskript liegt. In dem Beispiel unter /www/htdocs/<ftpuser>/backup/. Für dieses Verzeichnis müsst ihr entsprechend auch Schreibrechte setzen (chmod).

Über das Array $dbs werden die einzelnen Projekte definiert und die Datenbanken und Verzeichnisse festgelegt, für die ein Backup angelegt werden soll. In diesem Beispiel wird als erstes das Verzeichnis /www/htdocs/<ftp-username>/wordpress/ sowie ein Datenbankdump der Datenbank d1234567 in eine Datei wordpress_2013.05.01.tar.gz gepackt und unter /www/htdocs/<ftpuser>/backup/ abgelegt.

Als zweites passiert das gleiche für das Verzeichnis /www/htdocs/<ftp-username>/website/www und die Datenbank d321.

Das dritte tar.gz Paket enthält nur das Verzeichnis /www/htdocs/<ftp-username>/website/www und keine Datenbank.

Das vierte tar.gz Paket enthält nur ein Datenbankdump der Datenbank d987324.

Diese Liste kann man beliebig erweitern und man erhält so für jedes Projekt eine einzige tar.gz Datei. Legt man einen Cronjob an, so lässt sich beispielsweise ohne weiteren Aufwand ein wöchentliches Backup einrichten.

Das ganze Skript findet ihr auf github oder hier als ZIP zum download.

7 Comments

  1. m3adow
    2. Mai 2013

    Warum nutzt du all-inkl.com?
    Lächerliche 64 MB Memory Limit für PHP, dafür ein SSH-Zugriff sieht für mich nach einem unausgegorenen Tarifkonzept aus. Wie die Script execution times und script memory limits sind, will ich gar nicht erst wissen.
    Für 10€/Monat würde ich jedem empfehlen, eher einen eigenen vServer zu betreiben, da bekommt man sehr viel mehr für’s Geld und muss sich dann auch nicht wegen fehlender Extensions rumärgern.

  2. Tobi
    2. Mai 2013

    Finde all-inkl ganz gut. Für die 10 Euro gibts fünf Domains und man muss sich um keine Updates und Nichts kümmern. Mit einem vServer ist man da schnell wesentlich teurer unterwegs.

    Viele Grüße
    Tobi

  3. m3adow
    2. Mai 2013

    Nö ist man nicht.
    Beispielrechnung (schnell recherchiert, wäre vllt. noch optimierbar):
    – 1x vServer Pluto von Netcup: 5,49€/Monat
    – 5x .de-Domains inwx.de: 5×4,65€/Jahr +5×1,32€ Erstregistrierungsgebühr => 2,65€/Monat

    ==> 8,15/Monat
    Und das im ersten Jahr, für das zweite müsste man logischerweise die 5×1,32€ Erstregistrierungsgebühr herausrechnen.

    Du hast Recht, um Updates muss man sich nicht kümmern, aber wie du selbst sagst, hat das einige Nachteile. Die 64MB Memory Limit hast du selbst genannt, Execution time und Script memory weiß ich nicht, sind aber sicher auch sehr konservativ (lies: zu klein) gewählt.

    vServer sind sicherlich nicht für jeden gemacht, aber ich will doch darauf hinweisen, dass man für 10€ ein deutlich besseres Setup bekommt, bei dem man keine so großen Restriktionen hat (Subdomainbeschränkung, keine Wildcardomains, nur bestimmte PHP-Versionen, nur bestimmte PHP-Extensions, uvm.).

    PS: Warum kann man die Kommentare nicht per E-Mail abonnieren? :-(

  4. Daniel Ruf
    6. Mai 2013

    Keine Ahnung, was das Problem bei euch mit den Memory Limits und Max Execution Times ist.

    Man kann dies nämlich einfach per PHP zur Laufzeit erhöhen, klappt auch wunderbar bei uns bzw mir (bin auch bei all-inkl seit mindestens 2009)

    https://github.com/DanielRuf/Plain-of-JARs/blob/master/sources/websitebackup/jar_files/backup.php#L2

  5. Adrian
    13. Mai 2013

    Hallo Tobi,

    super Artikel, ich mache es so ähnlich, aber gleich von zu Hause.

    Ich lasse meine Seiten bei All-Inkl regelmäßig remote von meinem NAS sichern.

    Dateien geht recht einfach mit rsync gibt es sicher auch was für FTP. SSH pro Account zu aktivieren, braucht halt viel Speicherplatz.

    Da All-Inkl-Remotezugriff auf die DBs bietet kannst mysqldump ja auch einfach von extern anfertigen. Dann hast du nicht das Problem mit dem Limit auf dem Server.

  6. Stefan Brunnqual
    11. März 2014

    Hallo Tobi,
    super Script – vielen Dank.
    Gibt es evtl. die Möglichkeit einen Ordner beim Backup auszulassen?
    z.B. alles sichern, bis auf den Ordner Backup?

    Vielen Dank
    Stefan

  7. Michael Lambertz
    26. Juni 2014

    Hey vielen Dank für das Skript! Ist ne coole Sache. Ich frag mich nur ob all-inkl das so gerne sieht, dass man sich per php in ssh einloggt. Aber bisher die einzige Möglichkeit, die ich gefunden hab, das Dateisystem per Cron-Job zu sichern.
    Beste Grüße, Michael