CTO no Integrar Plus • Publicado em 13 de October de 2026
Copiar arquivos enquanto um processo grava nele quase sempre termina em arquivo quebrado. Quem administra servidor de Minecraft em VPS e deixa a instância rodando solta dentro de uma sessão do tmux costuma aprender isso do pior jeito: restaurando um backup de madrugada e encontrando cortes retos de terreno, chunks resetados para a seed original ou blocos desaparecidos porque o jogador abriu um baú no exato segundo em que o rsync passava pelo diretório region.
Existe uma divisão clara entre duas abordagens comuns nesse cenário. De um lado, administradores puristas defendem que backup seguro exige derrubar o processo Java, rodar a rotina de compactação com o servidor offline e subir tudo de novo. Do outro, quem prioriza disponibilidade sem atrito costuma montar um script ingênuo no cron que simplesmente dispara tar ou rsync direto contra a pasta do servidor em execução, torcendo para que a probabilidade estatística de colisão jogue a favor.
As duas posturas estão erradas. Derrubar o servidor a cada duas ou três horas para gerar snapshot quebra a experiência dos jogadores e introduz overhead desnecessário de aquecimento da JVM, leitura inicial de disco e recompilação JIT. Já rodar cópia cega enquanto a JVM mantém ponteiros abertos em arquivos .mca é negligência pura com integridade de dados.
O formato de região do Minecraft (Anvil) agrupa chunks em blocos de 32 por 32 em arquivos únicos. O servidor não regrava o arquivo inteiro a cada mudança. Ele atualiza cabeçalhos de alocação de setores e sobrescreve fatias internas à medida que jogadores exploram mapa, quebram blocos ou carregam entidades. Quando uma rotina externa de cópia lê os primeiros 4 KB com a tabela de setores e, no milissegundo seguinte, o jogo move um setor e grava o conteúdo sem atualizar a tabela que o script já leu, a cópia resultante nasce corrompida.
Para resolver isso sem interromper a execução no tmux, a coordenação precisa acontecer em duas etapas coordenadas: congelar a escrita da aplicação e capturar o estado no nível de blocos ou cópia física.
O protocolo nativo do servidor oferece os comandos necessários para essa pausa. Enviando instruções para o console do servidor via tmux com send-keys, você comanda a persistência imediata e desliga a gravação automática:
## Força gravação de tudo que está na memória para o disco e congela alterações
tmux send-keys -t minecraft "save-all flush" ENTER
tmux send-keys -t minecraft "save-off" ENTER
O comando save-all flush força a thread de I/O a descarregar todas as pendências da fila de chunks e dados de jogadores para os arquivos .mca e .dat. O modificador flush é crítico aqui porque, sem ele, versões modernas do Paper e do Vanilla apenas enfileiram o salvamento de forma assíncrona, retornando o controle ao console antes de os dados tocarem o disco de fato.
Logo em seguida, save-off instrui a engine a reter modificações posteriores na memória RAM, sem tocar os arquivos em disco. O mundo continua jogável, mas nenhuma alteração nova é persistida enquanto a flag estiver desligada.
Com o disco congelado, surge o problema de tempo. Se você mantiver o save-off ativo enquanto um tar.gz de 40 GB comprime a pasta inteira, a RAM do servidor vai acumular modificações até o Garbage Collector entrar em pânico ou o servidor cair por falta de memória se o tráfego de blocos for alto. A janela entre congelar e descongelar deve durar segundos, não minutos.
É aqui que o método de cópia define a sustentabilidade da rotina. Em servidores rodando sobre volumes ZFS, Btrfs ou LVM, o caminho técnico ideal é tirar um snapshot de sistema de arquivos instantâneo:
## Cria snapshot quase instantâneo
lvcreate --size 5G --snapshot --name mc-backup-snap /dev/vg0/minecraft
## Libera o servidor imediatamente
tmux send-keys -t minecraft "save-on" ENTER
Com o snapshot do volume criado, o save-on pode ser disparado em menos de cinco segundos. O processo de backup pesado (compactação, criptografia e upload para storage S3 ou B2) pode rodar montando o snapshot em leitura, sem disputa de I/O com a thread principal do jogo e sem risco de inconsistência.
Se você opera em VPS comum com ext4 sem suporte a snapshots no nível de bloco, a estratégia precisa recorrer a uma cópia intermediária rápida usando hard links ou rsync local:
## Cria snapshot de diretório usando hard links para arquivos inalterados
cp -al /srv/minecraft/world /srv/backups/staging/world-pending
## Reativa a gravação no servidor
tmux send-keys -t minecraft "save-on" ENTER
## Agora comprime fora da área crítica
tar -czf /srv/backups/world-$(date +%Y%m%d%H%M).tar.gz -C /srv/backups/staging world-pending
rm -rf /srv/backups/staging/world-pending
O uso de cp -al cria entradas de diretório novas apontando para os mesmos inodos em fração de segundo. Se o Minecraft voltar a gravar após o save-on, ele aloca novos setores ou reescreve blocos, mas a referência estática congelada no staging permanece intacta até o tar terminar de ler.
Existe, porém, um ponto cego que vejo a maioria das automações ignorar: a verificação de retorno do console. Mandar comandos com tmux send-keys é uma operação cega (fire-and-forget). Se o servidor estiver travado em um tick longo de GC ou o terminal tiver engolido o caractere, o script pode presumir que save-off foi aplicado quando na verdade o comando nem foi processado.
Para contornar essa fragilidade em scripts bash mais sérios, monitoro o arquivo logs/latest.log esperando a confirmação textual explícita da mensagem de salvamento antes de prosseguir com a cópia:
tail -F -n0 /srv/minecraft/logs/latest.log | while read line; do
case "$line" in
*"Saved the game"*|*"Automatic saving is now disabled"*)
break
;;
esac
done
Admito que essa conferência via parsing de log parece rústica quando comparada a uma API estruturada via RCON, mas o protocolo RCON do Minecraft possui vazamentos históricos de memória e adiciona uma porta de rede desnecessária para gerenciar localmente. A interface de pipes e sinais do próprio terminal tmux, combinada com inspeção de log local, entrega a menor superfície de contato e falha previsível.
Não existe mágica de consistência sem cooperação da camada da aplicação. Tratar uma JVM que grava dezenas de megabytes por segundo como se fosse um diretório de arquivos estáticos sempre cobra a conta no momento da restauração. Coordenar a parada de escrita no jogo com cópia atômica no sistema operacional é o único arranjo técnico que respeita a persistência dos dados sem precisar expulsar quem está jogando.
CTO e arquiteto full stack especializado em Ruby on Rails, Vue.js, sistemas multi-tenant e infraestrutura distribuída.