#!/bin/bash # Automated world backup — called by cron every 6 hours BACKUP_DIR="/home/minecraft/server/backups" WORLD_DIR="/home/minecraft/server/world" MAX_BACKUPS=20 RCON_PASS="23991818cc169249f181436f2a29a013" TIMESTAMP=$(date +%Y-%m-%d_%H-%M) mkdir -p "$BACKUP_DIR" # Check if server is running if systemctl is-active --quiet minecraft.service; then # Disable saving and flush node -e " const { Rcon } = require('/home/minecraft/dashboard/node_modules/rcon-client'); (async () => { try { const rcon = await Rcon.connect({ host: '127.0.0.1', port: 25575, password: '$RCON_PASS' }); await rcon.send('save-off'); await rcon.send('save-all flush'); rcon.end(); } catch {} })(); " sleep 3 fi # Create backup tar czf "$BACKUP_DIR/world_${TIMESTAMP}.tar.gz" -C /home/minecraft/server world # Validate backup was created and is non-empty if [ ! -s "$BACKUP_DIR/world_${TIMESTAMP}.tar.gz" ]; then echo "ERROR: Backup file is empty or missing" exit 1 fi # Re-enable saving if systemctl is-active --quiet minecraft.service; then node -e " const { Rcon } = require('/home/minecraft/dashboard/node_modules/rcon-client'); (async () => { try { const rcon = await Rcon.connect({ host: '127.0.0.1', port: 25575, password: '$RCON_PASS' }); await rcon.send('save-on'); rcon.end(); } catch {} })(); " fi # Prune old backups cd "$BACKUP_DIR" ls -t world_*.tar.gz 2>/dev/null | tail -n +$((MAX_BACKUPS + 1)) | xargs -r rm -f echo "Backup complete: world_${TIMESTAMP}.tar.gz"