WBCE CMS – Way Better Content Editing.
You are not logged in.
Der Text "Dateien, die mit einem Punkt beginnen, werden NICHT gesichert!" ist natürlich falsch, habe nicht aufgepasst.
Muß natürlich heissen: "Verzeichnisse die mit einem Punkt beginnen, werden NICHT gesichert!" (z.B. habe ich im root ein Verzeichnis ".vscode").
Der Text ist jetzt wieder entfernt.
Ich bin nicht ganz sicher, wie obige Aussage zu verstehen ist.
Bei meinen Tests werden alle Verzeichnisse und Dateien, die mit einem Punkt beginnen, ebenfalls mitgesichert.
Genauso, wie ich es erwarten würde.
Deshalb hatte ich den Text auch schon in meiner Version entfernt bzw. geändert.
Es gibt das WBCE Addon Repository, dort werden die aktuellen Versionen von florian eingestellt.
Ja, klar, das kenne ich. Ich meinte damit ein Sourcecode-Repository zur/während der Entwicklung, insbesondere, wenn mehrer Personen dran basteln...
Offline
Ja, du hast Recht, alle Verzeichnisse und Dateien, die mit Punkt beginnen werden gesichert (hatte falsch getestet).
Es werden nur die dot files (. und ..) in der Schleife übersprungen.
Zur Zeit gibt es kein Sourcecode Repository.
Offline
Zur Zeit gibt es kein Sourcecode Repository.
Ich habe einmal ein Repository bei GitHub angelegt und mit der Historie, soweit ich sie gefunden habe, gefüllt:
https://github.com/gchriz/wbce-backup-plus
Vielleicht hilft es ja irgendwie bei der Arbeit...
Offline
Kann man jetzt diese Version in das AOR stellen?
Offline
2.8.0 ist im Repo (nicht über die _1 dort wundern, hatte den Download sicherheitshalber nochmal ausgetauscht)
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Das mit dem Github-Repository ist nur eine Idee, ein Vorschlag, da WBCE selbst ja auch bei Github ist.
Jonglieren mit ZIP-Dateien aus Forumsbeiträgen finde ich eher umständlich und vor allem unübersichtlich.
Ich habe in meinem Repo die Versionen von BackupPlus, die im Laufe der Zeit ins AOR gegangen waren, mit Tags versehen.
So habe ich die Historie nachträglich zusammengestöpselt - ich bin ja erst seit 2.7.2 dabei.
Und so entspricht Tag "2.8.0" im Github-Repo der AOR-Version von Montag.
Ups... Das nachträgliche Historie-Bauen enthielt noch einen Fehler. Ich habe das Repo jetzt neu aufgebaut. Sorry...
Last edited by chriz (16.03.2022 15:44:50)
Offline
Anmerkung:
die Version in Github entspricht nicht der AOR Version.
Das zip File in Github enthält ein root Verzeichnis, damit kann man es nicht direkt im WBCE installieren, es muss vorher entpackt und dann neu ohne das root Verzeichnis gezippt werden, um es installieren zu können.
Ansonsten: sehr gute Arbeit, gut dokumentiert.
Last edited by mastermind (17.03.2022 12:33:59)
Offline
Anmerkung:
die Version in Github entspricht nicht der AOR Version.Das zip File in Github enthält ein root Verzeichnis, damit kann man es nicht direkt im WBCE installieren, es muss vorher entpackt und dann neu ohne das root Verzeichnis gezippt werden, um es installieren zu können.
Ups, stimmt. Aber wenn schon nicht von der Verpackung, so entspricht es zumindest inhaltlich.
Das mit dem root-Verzeichnis scheint ein Github-Feature zu sein. Mal sehen, ob sich das irgendwie ändern lässt...
Edit: Ich habe diesen Umstand jetzt erst einmal in der README.md eingetragen.
Last edited by chriz (17.03.2022 13:03:05)
Offline
Das zip File in Github enthält ein root Verzeichnis, damit kann man es nicht direkt im WBCE installieren, es muss vorher entpackt und dann neu ohne das root Verzeichnis gezippt werden, um es installieren zu können.
Das stimmt nicht. Github-Zips lassen sich bei WBCE grundsätzlich direkt, ohne vorheriges Umpacken, installieren. Das gilt auch für das Backup-Plus-Zip.
Last edited by florian (17.03.2022 14:44:11)
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Github-Zips lassen sich bei WBCE grundsätzlich direkt, ohne vorheriges Umpacken, installieren. Das gilt auch für das Backup-Plus-Zip.
Ohhh, danke, florian!
Ich habe echt schon gegrübelt, wie ich das per Script o.ä. hinkriege...
Offline
Es wäre super, wenn noch eine Automatisierungsfunktion ergänzt werden würde.
Meine Wünsche wären:
es gibt eine URL (mit einem Authentifizierungs-Parameter*), die sich per Cronjob aufrufen lässt, so dass regelmäßig ein Datenbank- und Dateisystembackup erzeugt wird - wie gehabt mit Zufallszeichen im Dateinamen.
Es werden immer nur eine bestimmte, konfigurierbare Anzahl von Vorversionen gespeichert, nach dem First in/first-Out-Prinzip wird bei erfolgreichem Backup die älteste Version gelöscht.
An eine konfigurierbare E-Mail-Adresse wird eine Benachrichtigung gesendet, sobald ein Backup erstellt wurde (oder es zu Problemen kam).
* Damit meine ich, dass das Erstellen des Backups sich nicht einfach durch z.B. /modules/backup_plus/autobackup.php starten lässt, sondern dass noch ein (im Backend generierter und gespeicherter) Token übergeben werden muss, also so was wie autobackup.php?token=$5ghfhgf54546
Wäre so etwas umsetzbar? Etwas Budget zur Motivationsförderung wäre auch vorhanden.
Last edited by florian (31.03.2022 11:43:53)
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Hallo Zusammen,
leider klappt die Gesamtsicherung plötzlich nicht mehr - dh. sie hatte bis April noch funktioniert und seit heute aus unerfindlichen Gründen nicht mehr.
Fehlermeldung 500 - .../modules/backup_plus/backup.php
Habe auch kontrolliert, dass das Verzeichnis, in dem ich neue Medien gelegt habe, auch Schreibrechte hat.
Provider ist 1Blu - aber wie gesagt, bis April ist alles super gelaufen.
Habe die neueste Version des Plugins.
viele Grüße
Ingrid
Offline
Hallo Zusammen,
anscheinend war es ein Problem bei 1Blu - heute habe ich einfach die Sicherung nochmal versucht und die Sicherung lief ohne Probleme durch.
Offline
PHP 8.1 ist ja bekanntermaßen extra pinzig. Die Zeile 342 in der backup.php
$sql_code .= "`".$insert ."`='".addslashes($value)."',";
verursacht Deprecated-Einträge im Errorlog.
Ich habe das jetzt so gelöst, dass ich da eine Prüfung voranstelle, ob $value nicht leer ist:
foreach ($code as $insert => $value) {
if ($value!==null) {
$ValueToInsert = addslashes($value);
} else {
$ValueToInsert = '';
}
$sql_code .= "`".$insert ."`='".$ValueToInsert."',";
}
Wenn man das noch elegenater lösen kann, bitte gerne umsetzen, ansonsten würde ich die gefixte Version als 2.8.1 ins AOR stellen...
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Hallo,
auf zwei Seiten mit frischem Update 1.5.3 erscheint beim Backup Plus die Meldung unter dem Button >>Ausgewählte Sicherung starten<< der Hinweis ...
[== HTML ==]
Status: 403
Forbidden
URL: https://meinedomian.de/modules/backup_plus/list.php
Die Übersicht bereits getätigter Sicherungen oben rechts ist nicht zu sehen. Die Auswahl einer Sicherung kann ich noch tätigen.
Was könnt das sein?
Viele Grüße,
Klaus
PS: Backup Plus auch noch mal frisch installiert, altes Backup ohne plus deinstalliert.
Macht's gut und danke für den Fisch!
Offline
Es kann beim Update manchmal dazu kommen, dass die Zugriffsrechte falsch gesetzt werden. Bitte mal bei den Grundeinstellungen > Erweiterte Optionen anzeigen schauen, was da für Zugriffsrechte für Dateien und Verzeichnisse eingestellt ist und ggfs. auf 0644 / 0755 setzen.
Das das nicht rückwirkend angewendet wird: Zugriffsrechte für das Backup-Verzeichnis manuell anpassen (mit FTP-Programm Rechtsklick auf Verzeichnis und dann Verzeichniseigenschaften, Zugriffsrechte o.ä.)
Last edited by florian (07.10.2022 09:30:32)
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
cyberdyne
Hallo Zusammen,
leider klappt die Gesamtsicherung nicht bei großen Installationen mit vielen Dateien - dh. die ZIP-Datei wird angeblich fertig geschrieben, jedoch fehlen Dateien und etliche MB Größe der ZIP-Datei.
Die Datenbank wird im Anschluss nicht gesichert und das Script bricht mit der „Fehlermeldung 500 - .../modules/backup_plus/backup.php“ ab.
Schließe ich das media Verzeichnis aus, bzw. die großen Unterverzeichnisse, läuft alles.
Ein Dateigrößen Limit bringt nichts, da die 2,1 GB durch pure Masse erreicht werden.
Habe die neueste Version des Plugins.
Offline
Das kann ich leider bestätigen. Auch an sehr großen Datenbanktabellen verschluckt sich das Script bisweilen, ist mir aufgefallen.
Ich denke, das hängt mit serverseitigen Speicherlimits zusammen, wenn das Memorylimit auf 128M oder so steht, dass das schlichtweg nicht ausreicht, um riesige Dateien zu zippen oder tausende Einträge umfassende Tabellen zu sichern. Mir ist leider keine Möglichkeit bekannt, wie sich das umgehen ließe.
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Gibt es Erkenntnisse, darüber, bei wie vielen Hostern die exec Funktion verfügbar ist? Auf der Mehrheit der Linux Server müsste tar verfügbar sein. Damit funktioniert testweise zumindest die Sicherung perfekt.
Last edited by mathias (10.11.2023 16:13:33)
Offline
Tendenziell wäre ich da skeptisch, ob auf Shared-Hosting-Webspace exec verfügbar ist. Wobei ich da von Fachwissen komlett unvorbelastet bin.
Mal abgesehen davon, dass das Durchschnittsnutzy wahrscheinlich mit einer .tar(.gz)-Datei nichts anfangen kann (es hat ja nicht jeder 7-Zip istalliert), scheint es mir aber so zu sein, dass es auch dafür eine PHP-Extension gibt (wobei natürlich die Frage ist, ob und wo die überall verfügbar ist), vgl.
https://stackoverflow.com/questions/455 … -using-php
https://gist.github.com/hslatman/3933ec59df39e358fa68
Könnte das etwas ändern?
Sorgen sind wie Nudeln: man macht sich meist zu viele.
Offline
Ich glaube nicht, dass das etwas ändert, da die Speichergrenzen von php dann vermutlich auch greifen würden.
Sind ja eh zwei Baustellen.
Zum einen die Speichergrenzen, die man ggf. durch exec austricksen könnte.
Hier einfach mal an alle, die irgendwo Webspace haben und dazu etwas sagen können: Läuft bei euch exec?
Zweitens die Überlegung zip durch tar.gz zu ersetzen und damit eine ggf. vorhandene 4GB Grenze zu durchbrechen.
Offline
So wie es aussieht habe ich einen unangenehmen Bug in Backup Plus gefunden...
Kurz zur Historie: Ich restore regelmäßig eine kleine Produktivinstanz von WBCE auf eine lokale Testinstanz. Dazu nutze ich Backup Plus. Oft hat es in der Vergangenheit (wohl) funktioniert...
Aber nun ist mir Folgendes aufgefallen: Der Restore war schnell fertig (sind auch nur ein paar MB) und wurde als erfolgreich gemeldet (im Log und im Backend), aber die Datenbank war nicht (vollständig) wiederhergestellt. Reproduzierbar.
Ein manueller Restore mit dem mysql CLI klappte dagegen problemlos, also lag es nicht an der SQL-Datei.
Nach längerer Jugend-forscht-Arbeit habe ich die Ursache gefunden.
Das Einlesen der SQL-Datei in restore.php geschieht mit multi_query():
[== PHP ==]
/**
-------------------------------------------------------------------------------
*
* IMPORT THE SQL EXPORT FILE
*
-------------------------------------------------------------------------------
**/
$sqlfile = str_replace('.zip', '.sql', $zipfile);
$sql = file_get_contents($sqlfile);
if ($sql === false) {
abort(array('code' => 4035, 'error' => $MOD_BACKUP['BACKUP_READ_SQL_ERROR']));
}
// execute multi query
$db = $database->__get('db_handle');
if (!($db->multi_query($sql))) {
abort(array('code' => 4036, 'error' => print_r($db->error,true)));
}
$log->write( sprintf('Restore SQL dump "%s" sucessfull', $sqlfile));
$log->write('Restore finished successfully');
$log->close();
abort(array('code' => 200, 'error' => '', 'message' => sprintf($MOD_BACKUP['BACKUP_RESTORED'])));
Leider wird aber dort nicht vollständig geprüft, ob der Restore auch (komplett!) erfolgreich ist. Nur der erste Query des asynchronen(!!!) multi_query() wird abgefragt, alle weiteren aus der zu restorenden SQL-Datei nicht!
Es wird immer ein "successful" gemeldet, auch wenn unterwegs etwas schief geht. Weder im Backend noch im Log tauchen Fehlermeldungen auf.
Siehe dazu: https://www.php.net/manual/en/mysqli.multi-query.php
Und insbesondere den Nutzerkommentar hier: https://www.php.net/manual/de/mysqli.qu … tement.php
Mein aktueller Zwischenstand zur Fehlererkennung ist dies (noch nicht bereinigt):
[== PHP ==]
$sqlfile = str_replace('.zip', '.sql', $zipfile);
$sql = file_get_contents($sqlfile);
if ($sql === false) {
abort(array('code' => 4035, 'error' => $MOD_BACKUP['BACKUP_READ_SQL_ERROR']));
}
// since the later multi_query() is processed asynchronously the logging lines need to be changed as so:
$log->write( sprintf('Restore SQL dump "%s" should have finished successfully if there are no error messages following!', $sqlfile));
//$log->write('Restore finished successfully');
// execute multi query
$db = $database->__get('db_handle');
if (!($db->multi_query($sql))) {
$log->write(print_r($db->error,true));
abort(array('code' => 4036, 'error' => $db->errno . " -1- " . print_r($db->error,true)));
}
do {
if (!($db->next_result())) {
$log->write($db->errno . " - " . print_r($db->error,true));
// Cannot delete or update a parent row: a foreign key constraint fails
$log->write($db->info); // empty string
$log->write($db->affected_rows); // -1
abort(array('code' => 4036, 'error' => $db->errno . " -2- " . print_r($db->error,true)));
}
$log->write('.');
} while ($db->more_results());
if (0 !== $db->errno) {
abort(array('code' => 4036, 'error' => $db->errno . " -3- " . print_r($db->error,true)));
}
$log->close();
abort(array('code' => 200, 'error' => '', 'message' => sprintf($MOD_BACKUP['BACKUP_RESTORED'])));
Außerdem habe ich die abort() Funktion temporär etwas gesprächiger gemacht, um den Abbruch sofort zu sehen:
[== PHP ==]
function abort($status) {
global $matches;
if (empty($status["error"])) {
$s = 'result=' . urlencode($status["message"]);
} else {
$s = 'result=false&error=' . urlencode($status["error"].'<br>Code: '.$status["code"]);
}
// if ($matches[2] == 'p') {
header("Location: " . ADMIN_URL . '/admintools/tool.php?tool=backup_plus&'.$s);
//} else {
// header("Location: " . ADMIN_URL . '/login/');
//}
exit;
}
Auf diese Weise erfahre ich, dass bei meinem Restore ein "Cannot delete or update a parent row: a foreign key constraint fails" auftritt. Immerhin.
Aber es wird nicht deutlich, wo/warum das passiert. Und ich habe das dem $db auch noch nicht entlocken können.
Vermutlich ist multi_query() hier nicht die optimale Lösung... ?!?!
Ich werde noch weiter testen...
Offline
florian
Schon einmal zwei Ergänzungen:
1.) Zu der bei mir auftretenden Fehlermeldung "Cannot delete or update a parent row: a foreign key constraint fails"
Die einzige Stelle mit offensichtlichen CONSTRAINTS in der SQL-Datei ist
# Create table hhk_mod_news_img_posts_img
CREATE TABLE `hhk_mod_news_img_posts_img` (
`post_id` int NOT NULL,
`pic_id` int NOT NULL,
`position` int NOT NULL,
UNIQUE KEY `post_id_pic_id` (`post_id`,`pic_id`),
KEY `FK_hhk_mod_news_img_posts_img_hhk_mod_news_img_img` (`pic_id`),
CONSTRAINT `FK_hhk_mod_news_img_posts_img_hhk_mod_news_img_img` FOREIGN KEY (`pic_id`) REFERENCES `hhk_mod_news_img_img` (`id`) ON DELETE CASCADE ON UPDATE CASCADE,
CONSTRAINT `FK_hhk_mod_news_img_posts_img_hhk_mod_news_img_posts` FOREIGN KEY (`post_id`) REFERENCES `hhk_mod_news_img_posts` (`post_id`) ON DELETE CASCADE ON UPDATE CASCADE
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb3;
Die CONSTRAINTS einfach dort herauszunehmen hat nicht geholfen. (Ich bin kein SQL-Experte...)
Den Fehler kann ich aber unterdrücken, indem ich die SQL-Datei editiere und ein SET FOREIGN_KEY_CHECKS=0; voranstelle. Das ist natürlich keine endgültige Lösung, aber ein Hinweis auf eine Ursache.
2.) Mein temporäres restore.php in #122 hat noch das "Problem", auch im Okay-Fall in der Liste der Logfiles im Backend die Wiederherstellung als "rot" anzuzeigen.
Das liegt daran, dass list.php einfach nach dem Text 'finished successfully' sucht, der ja nicht mehr vorhanden ist und es aktuell wegen der Asynchronität auch nicht sein kann/darf.
Offline
Folgender Codeschnipsel für restore.php klappt nun bei mir.
Im Restore-Erfolgsfall ist list.php zufrieden und im Backend wird auch ein Erfolg angezeigt.
Bei einem Fehler unterwegs im multi_query() wird der in die Logdatei geschrieben und das Ergebnis ist "rot" im Backend.
Damit die abort() Funktion im Fehlerfall auch etwas anzeigt, siehe nächster Beitrag...
[== PHP ==]
/**
-------------------------------------------------------------------------------
*
* IMPORT THE SQL EXPORT FILE
*
-------------------------------------------------------------------------------
**/
$sqlfile = str_replace('.zip', '.sql', $zipfile);
$sql = file_get_contents($sqlfile);
if ($sql === false) {
abort(array('code' => 4035, 'error' => $MOD_BACKUP['BACKUP_READ_SQL_ERROR']));
}
$log->write( sprintf('Restoring SQL dump "%s" ...', $sqlfile));
// execute multi query
$db = $database->__get('db_handle');
// Possibly this might help too???:
// mysqli_report(MYSQLI_REPORT_ERROR | MYSQLI_REPORT_STRICT);
if (!($db->multi_query($sql))) {
$log->write($db->errno . " - " . print_r($db->error,true));
abort(array('code' => 4036, 'error' => $db->errno . " - " . print_r($db->error,true)));
}
do {
$db->next_result();
// This shows the internal steps within multi_query().
// Unfortunately without detailed data available.
//$log->write('.');
} while ($db->more_results());
if ($db->error) {
$log->write($db->errno . " - " . print_r($db->error,true));
abort(array('code' => 4036, 'error' => $db->errno . " - " . print_r($db->error,true)));
}
$log->write('Restore finished successfully');
$log->close();
abort(array('code' => 200, 'error' => '', 'message' => sprintf($MOD_BACKUP['BACKUP_RESTORED'])));
/*****************************************************************************************************/
Der Punkt 1.) von #123 ist allerdings weiterhin ungeklärt.
Aber das ist ja auch eigentlich eine zweite Baustelle, Hauptsache der/ein Fehler wird überhaupt sichtbar.
Edit: Code noch einmal verbessert am 02.03.2024 06:37
Last edited by chriz (02.03.2024 07:36:51)
Offline
... und damit ein eventueller Fehler beim Restore auch sofort im Backend sichtbar wird, habe ich abort() in restore.php minimal angepasst:
[== PHP ==]
function abort($status) {
global $matches;
if (empty($status["error"])) {
$s = 'result=' . urlencode($status["message"]);
} else {
$s = 'result=false&error=' . urlencode($status["error"].'<br>Code: '.$status["code"]);
}
if (($matches[2] == 'p') || (! empty($status["error"]))) {
header("Location: " . ADMIN_URL . '/admintools/tool.php?tool=backup_plus&'.$s);
} else {
header("Location: " . ADMIN_URL . '/login/');
}
exit;
}
Offline