fix: lokale Dump-Datei immer löschen (try/finally)
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
+51
-48
@@ -77,57 +77,60 @@ async function runBackup(): Promise<void> {
|
||||
await dumpToFile(localPath);
|
||||
console.log(`[backup] Dump geschrieben: ${localPath}`);
|
||||
|
||||
if (!sshUrl) return;
|
||||
try {
|
||||
if (!sshUrl) return;
|
||||
|
||||
const match = sshUrl.match(/^([^:]+):(.+)$/);
|
||||
if (!match) {
|
||||
console.error('[backup] BACKUP_SSH_URL muss das Format user@host:/pfad haben');
|
||||
return;
|
||||
}
|
||||
const [, sshHost, remotePath] = match;
|
||||
const match = sshUrl.match(/^([^:]+):(.+)$/);
|
||||
if (!match) {
|
||||
console.error('[backup] BACKUP_SSH_URL muss das Format user@host:/pfad haben');
|
||||
return;
|
||||
}
|
||||
const [, sshHost, remotePath] = match;
|
||||
|
||||
const rawKeyPath = process.env.BACKUP_SSH_KEY_PATH || '';
|
||||
const keyPath = rawKeyPath.startsWith('~')
|
||||
? rawKeyPath.replace('~', process.env.HOME || '/root')
|
||||
: rawKeyPath;
|
||||
const rawKeyPath = process.env.BACKUP_SSH_KEY_PATH || '';
|
||||
const keyPath = rawKeyPath.startsWith('~')
|
||||
? rawKeyPath.replace('~', process.env.HOME || '/root')
|
||||
: rawKeyPath;
|
||||
|
||||
const sshOpts = [
|
||||
...(keyPath ? ['-i', keyPath] : []),
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'-o', 'BatchMode=yes',
|
||||
'-o', 'ConnectTimeout=15',
|
||||
];
|
||||
const sshOpts = [
|
||||
...(keyPath ? ['-i', keyPath] : []),
|
||||
'-o', 'StrictHostKeyChecking=no',
|
||||
'-o', 'BatchMode=yes',
|
||||
'-o', 'ConnectTimeout=15',
|
||||
];
|
||||
|
||||
// Zielverzeichnis auf Remote anlegen falls nicht vorhanden
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const ssh = spawn('ssh', [...sshOpts, sshHost, `mkdir -p ${remotePath}`]);
|
||||
ssh.on('error', reject);
|
||||
ssh.on('close', (code) => code === 0 ? resolve() : reject(new Error(`mkdir -p exit ${code}`)));
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const scp = spawn('scp', [...sshOpts, localPath, `${sshHost}:${remotePath}/${filename}`]);
|
||||
let scpErr = '';
|
||||
scp.stderr.on('data', (d: Buffer) => { scpErr += d.toString(); });
|
||||
scp.on('error', reject);
|
||||
scp.on('close', (code) =>
|
||||
code === 0 ? resolve() : reject(new Error(`scp exit ${code}${scpErr ? ': ' + scpErr.trim() : ''}`))
|
||||
);
|
||||
});
|
||||
|
||||
unlinkSync(localPath);
|
||||
console.log(`[backup] ${filename} → ${sshHost}:${remotePath}`);
|
||||
|
||||
// Backups älter als 30 Tage auf Remote löschen
|
||||
await new Promise<void>((resolve) => {
|
||||
const ssh = spawn('ssh', [
|
||||
...sshOpts, sshHost,
|
||||
`find ${remotePath} -name 'sternwarte_*.sql.gz' -mtime +30 -delete`,
|
||||
]);
|
||||
ssh.on('error', (e) => { console.error('[backup] Cleanup spawn-Fehler:', e.message); resolve(); });
|
||||
ssh.on('close', (code) => {
|
||||
if (code !== 0) console.error('[backup] Cleanup fehlgeschlagen (exit ' + code + ')');
|
||||
resolve();
|
||||
// Zielverzeichnis auf Remote anlegen falls nicht vorhanden
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const ssh = spawn('ssh', [...sshOpts, sshHost, `mkdir -p ${remotePath}`]);
|
||||
ssh.on('error', reject);
|
||||
ssh.on('close', (code) => code === 0 ? resolve() : reject(new Error(`mkdir -p exit ${code}`)));
|
||||
});
|
||||
});
|
||||
|
||||
await new Promise<void>((resolve, reject) => {
|
||||
const scp = spawn('scp', [...sshOpts, localPath, `${sshHost}:${remotePath}/${filename}`]);
|
||||
let scpErr = '';
|
||||
scp.stderr.on('data', (d: Buffer) => { scpErr += d.toString(); });
|
||||
scp.on('error', reject);
|
||||
scp.on('close', (code) =>
|
||||
code === 0 ? resolve() : reject(new Error(`scp exit ${code}${scpErr ? ': ' + scpErr.trim() : ''}`))
|
||||
);
|
||||
});
|
||||
|
||||
console.log(`[backup] ${filename} → ${sshHost}:${remotePath}`);
|
||||
|
||||
// Backups älter als 30 Tage auf Remote löschen
|
||||
await new Promise<void>((resolve) => {
|
||||
const ssh = spawn('ssh', [
|
||||
...sshOpts, sshHost,
|
||||
`find ${remotePath} -name 'sternwarte_*.sql.gz' -mtime +30 -delete`,
|
||||
]);
|
||||
ssh.on('error', (e) => { console.error('[backup] Cleanup spawn-Fehler:', e.message); resolve(); });
|
||||
ssh.on('close', (code) => {
|
||||
if (code !== 0) console.error('[backup] Cleanup fehlgeschlagen (exit ' + code + ')');
|
||||
resolve();
|
||||
});
|
||||
});
|
||||
} finally {
|
||||
try { unlinkSync(localPath); } catch { /* bereits gelöscht oder nie angelegt */ }
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user