105 lines
3.6 KiB
JavaScript
105 lines
3.6 KiB
JavaScript
#!/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);
|
||
}
|
||
|