nakama/backend/scripts/backup.js

106 lines
3.6 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

#!/usr/bin/env node
/**
* Скрипт для автоматического бэкапа MongoDB
* Использование: node scripts/backup.js
* Или добавить в cron: 0 2 * * * node /path/to/scripts/backup.js
*/
const { execSync } = require('child_process');
const fs = require('fs');
const path = require('path');
const dotenv = require('dotenv');
// Загрузить переменные окружения
dotenv.config({ path: path.join(__dirname, '../.env') });
const MONGODB_URI = process.env.MONGODB_URI || 'mongodb://localhost:27017/nakama';
const BACKUP_DIR = process.env.BACKUP_DIR || path.join(__dirname, '../backups');
const MAX_BACKUPS = parseInt(process.env.MAX_BACKUPS || '30'); // Хранить 30 бэкапов
// Парсинг MongoDB URI для получения имени базы данных
function getDatabaseName(uri) {
try {
const match = uri.match(/\/([^/?]+)/);
return match ? match[1] : 'nakama';
} catch {
return 'nakama';
}
}
// Парсинг MongoDB URI для получения хоста и порта
function getMongoHost(uri) {
try {
const url = new URL(uri);
return `${url.hostname}:${url.port || 27017}`;
} catch {
return 'localhost:27017';
}
}
// Создать директорию для бэкапов
if (!fs.existsSync(BACKUP_DIR)) {
fs.mkdirSync(BACKUP_DIR, { recursive: true });
}
// Имя базы данных
const dbName = getDatabaseName(MONGODB_URI);
const mongoHost = getMongoHost(MONGODB_URI);
// Имя файла бэкапа
const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
const backupName = `backup-${dbName}-${timestamp}`;
const backupPath = path.join(BACKUP_DIR, backupName);
console.log(`📦 Создание бэкапа базы данных: ${dbName}`);
console.log(`📁 Путь: ${backupPath}`);
console.log(`🖥️ Хост: ${mongoHost}`);
try {
// Создать бэкап с помощью mongodump
const command = `mongodump --host ${mongoHost} --db ${dbName} --out ${backupPath}`;
console.log(`🔄 Выполнение команды: ${command}`);
execSync(command, { stdio: 'inherit' });
console.log(`✅ Бэкап создан успешно: ${backupPath}`);
// Архивировать бэкап
const archivePath = `${backupPath}.tar.gz`;
console.log(`📦 Архивирование бэкапа...`);
execSync(`tar -czf ${archivePath} -C ${BACKUP_DIR} ${backupName}`, { stdio: 'inherit' });
// Удалить неархивированную директорию
execSync(`rm -rf ${backupPath}`, { stdio: 'inherit' });
console.log(`✅ Архив создан: ${archivePath}`);
// Удалить старые бэкапы
const backups = fs.readdirSync(BACKUP_DIR)
.filter(file => file.startsWith(`backup-${dbName}-`) && file.endsWith('.tar.gz'))
.map(file => ({
name: file,
path: path.join(BACKUP_DIR, file),
time: fs.statSync(path.join(BACKUP_DIR, file)).mtime
}))
.sort((a, b) => b.time - a.time);
if (backups.length > MAX_BACKUPS) {
const toDelete = backups.slice(MAX_BACKUPS);
console.log(`🗑️ Удаление старых бэкапов (${toDelete.length} файлов)...`);
toDelete.forEach(backup => {
fs.unlinkSync(backup.path);
console.log(` Удален: ${backup.name}`);
});
}
console.log(`✅ Бэкап завершен успешно`);
console.log(`📊 Всего бэкапов: ${backups.length}`);
} catch (error) {
console.error(`❌ Ошибка создания бэкапа:`, error.message);
process.exit(1);
}