Upload via GUI (338 Dateien)
This commit is contained in:
@@ -60,7 +60,9 @@ Deny from all
|
||||
|
||||
// Zeitlimit erhöhen für große Backups
|
||||
@set_time_limit(300);
|
||||
@ini_set('memory_limit', '256M');
|
||||
// Arbeitsspeicher nur erhöhen, nie senken (ein Limit von 512 MB oder mehr vom Hoster bleibt erhalten)
|
||||
$memBytes = (function (string $v): int { $n = (int) $v; return match (strtolower(substr(trim($v), -1))) { 'g' => $n * 1073741824, 'm' => $n * 1048576, 'k' => $n * 1024, default => $n }; })((string) ini_get('memory_limit'));
|
||||
if ($memBytes >= 0 && $memBytes < 512 * 1048576 && $memBytes !== 0) { @ini_set('memory_limit', '512M'); }
|
||||
|
||||
// php_zip automatisch aktivieren falls nicht geladen
|
||||
if (!class_exists('ZipArchive')) {
|
||||
@@ -96,6 +98,10 @@ Deny from all
|
||||
|
||||
// Alle Dateien sammeln
|
||||
$exclude = [realpath($backupDir) ?: $backupDir];
|
||||
// Der Backup-Ordner des Servers (backups/) gehört NIE ins Backup, auch wenn das Ziel ein anderer Ordner ist (zum Beispiel ein Zwischenordner des
|
||||
// NAS-Plugins): sonst steckten alle älteren Backups noch einmal darin. Nur die .htaccess bleibt dabei, damit der Ordner nach einer
|
||||
// Wiederherstellung geschützt ist.
|
||||
$stdBackups = realpath($rootDir . '/backups') ?: null;
|
||||
$iter = new RecursiveIteratorIterator(
|
||||
new RecursiveDirectoryIterator($rootDir, RecursiveDirectoryIterator::SKIP_DOTS),
|
||||
RecursiveIteratorIterator::SELF_FIRST
|
||||
@@ -107,8 +113,12 @@ Deny from all
|
||||
$filePath = $file->getRealPath();
|
||||
$norm = str_replace('\\', '/', $filePath);
|
||||
$skip = false;
|
||||
foreach ($exclude as $ex) {
|
||||
if ($ex && strpos($filePath, $ex) === 0) { $skip = true; break; }
|
||||
if ($stdBackups !== null && strpos($filePath, $stdBackups . DIRECTORY_SEPARATOR) === 0) {
|
||||
if ($filePath !== $stdBackups . DIRECTORY_SEPARATOR . '.htaccess') $skip = true; // alles außer der .htaccess
|
||||
} else {
|
||||
foreach ($exclude as $ex) {
|
||||
if ($ex && ($filePath === $ex || strpos($filePath, rtrim($ex, '/' . chr(92)) . DIRECTORY_SEPARATOR) === 0)) { $skip = true; break; }
|
||||
}
|
||||
}
|
||||
foreach (backup_excluded_fragments() as $frag) {
|
||||
if (str_contains($norm, $frag)) { $skip = true; break; }
|
||||
@@ -205,8 +215,13 @@ Deny from all
|
||||
if ($zip->open($backupPath, ZipArchive::CREATE | ZipArchive::OVERWRITE) !== true) {
|
||||
return ['ok' => false, 'error' => 'Backup-ZIP konnte nicht erstellt werden.'];
|
||||
}
|
||||
$canStore = method_exists($zip, 'setCompressionName');
|
||||
foreach ($files as $filePath => $relativePath) {
|
||||
$zip->addFile($filePath, $relativePath);
|
||||
// Bereits komprimierte Dateien nur ablegen statt erneut zu packen: spart bei großen Uploads viel Rechenzeit
|
||||
if ($canStore && preg_match('/\.(zip|jpe?g|png|gif|webp|pdf|exe|apk|aab|jar|7z|gz|mp[34]|woff2?)$/i', $relativePath)) {
|
||||
@$zip->setCompressionName($relativePath, ZipArchive::CM_STORE);
|
||||
}
|
||||
}
|
||||
if ($sqlDump && $sqlFile) $zip->addFromString($sqlFile, $sqlDump);
|
||||
if ($sqliteSnapshot) $zip->addFile($sqliteSnapshot, 'database_backup.sqlite');
|
||||
@@ -276,3 +291,19 @@ Deny from all
|
||||
'size' => round(filesize($backupPath) / 1024 / 1024, 2),
|
||||
];
|
||||
}
|
||||
|
||||
/**
|
||||
* Sperre „es läuft gerade ein Backup“: höchstens ein Backup gleichzeitig (Cronjob, eingebauter Hintergrunddienst, Knopf auf der Seite, NAS-Plugin).
|
||||
* Atomar über die Einstellungstabelle; eine Sperre älter als $maxSeconds (abgestürzter Lauf) gilt als frei.
|
||||
*/
|
||||
function backup_lock_acquire(PDO $pdo, int $maxSeconds = 10800): bool
|
||||
{
|
||||
if (!function_exists('pseudo_cron_try_claim')) return true;
|
||||
return pseudo_cron_try_claim($pdo, 'backup_run_lock', $maxSeconds);
|
||||
}
|
||||
|
||||
function backup_lock_release(PDO $pdo): void
|
||||
{
|
||||
if (!function_exists('pseudo_cron_try_claim')) return;
|
||||
try { $pdo->prepare("UPDATE settings SET setting_value = '1970-01-01 00:00:00' WHERE setting_key = 'backup_run_lock'")->execute(); } catch (Throwable $e) { /* Sperre verfällt von selbst */ }
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user