nakama/backend/scripts/backup.js

105 lines
3.6 KiB
JavaScript
Raw Normal View History

2025-11-04 21:51:05 +00:00
#!/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);
}