Gerando backup automático do Minecraft quando o servidor estiver vazio (Linux/Bash)
Overview
Neste post superinteressante, você vai descobrir como proteger o seu mundo no Minecraft de desastres inesperados com um script de backup bastante eficaz. Se o seu servidor não é dos mais confiáveis, ou se simplesmente quer garantir que todo o seu esforço construindo e explorando não vá por água abaixo, você está no lugar certo! Através de um guia detalhado, com passos claros e objetivos, você aprenderá a implementar uma solução de backup que roda de forma automática, sem necessidade da sua intervenção constante. Preparado para evitar dores de cabeça e garantir que seu mundo no Minecraft esteja sempre seguro? Então, siga com a leitura!
Um dos problemas de ter um servidor de Minecraft hospedado em um servidor não muito confiável (tipo o CloudAtCost) é que você corre o risco de perder o progresso do seu mundo e ter que começar tudo de novo. Neste post, mostro o exemplo do script que eu fiz para automatizar o backup.
Se a ideia de um backup automático é interessante para você, então leia este post. Ele pode te dar algum insight.
O que acontece é o seguinte: A cada 6 horas, o script verifica se o servidor está vazio (sem ninguém conectado). Se estiver, ele gera um novo backup (archive) e apaga os velhos (para não ficar muito pesado no lado do armazenamento).
A automatização utiliza apenas um bash script, considera uma instalação do Minecraft com o MineOS e adiciona algumas linhas no log do Minecraft, para você conseguir acompanhar quando um backup foi feito. Sei que ele não é perfeito, pois o backup ainda fica armazenado na própria maquina do servidor. Em um post futuro, vou fazer outra versão deste script que seja integrado com o Dropbox ou Onedrive…
Vamos ao script.
Definição de variáveis
Primeiro passo é definir as variáveis que vamos precisar:
# Base config
minecraft_folder="/var/games/minecraft"
servers_folder="servers"
archives_folder="archive"
logs_folder="logs"
world_name="WorldOfOurCraft"
latest_log_folder="$minecraft_folder/$servers_folder/$world_name/$logs_folder"
latest_log="$latest_log_folder/latest.log"
text_to_search="left the game"
backup_filename="server_$world_name$(date +"_%Y%m%d_%H%M%S").tar.gz"
backup_file="$minecraft_folder/$archives_folder/$world_name/$backup_filename"
backup_source_files="$minecraft_folder/$servers_folder/$world_name"
max_backup_days=14
Uma explicação rápida para cada uma destas variáveis:
- minecraft_folder: Diretório onde está instalado o Minecraft
- servers_folder: Diretório onde ficam os servidores
- archives_folder: Diretório onde ficam os backups (archive)
- logs_folder: Diretório de logs
- world_name: Nome do seu servidor
- latest_log_folder: Diretório onde está o log “latest.log”
- latest_log: Caminho completo para o arquivo “latest.log”
- text_to_search: Texto que será procurado no log
- backup_filename: Nome do backup que vai ser gerado. ele inclui um timestamp com o formato: aaaammdd_hhmmss
- backup_file: Caminho completo para o arquivo de backup
- backup_source_files: Caminho para os arquivos que serão incluídos no backup.
- max_backup_days: Número máximo de dias que um backup pode ter. Arquivos criados ha mais tempo (em dias) do que o valor desta variável, serão apagados.
Seria possível diminuir a quantidade de variáveis, mas achei assim mais simples/didático. você deve alterar as que forem pertinentes para a sua instalação.
Verificação do log
O segundo passo é extrair a última linha do log atual (latest.log), se ela possuir um determinado texto:
last_log_line=$(tail -n 1 $latest_log | grep -a "$text_to_search")
Este comando vai ler o arquivo e salvar a ultima linha do log, se ela possuir o texto “left the game”, que é o texto padrão que o Minecraft escreve quando um usuário se desconecta do servidor. O pulo do gato está neste ponto. Enquanto as pessoas estão jogando ou quando o mundo está sendo carregado, o servidor escreve diversas coisas no log. Assim que um usuário se desconecta, ele escreve “<nome do jogador> left the game” e se ninguém mais estiver jogando, esta será a última linha do log.
O comando em si é bem simples:
- Primeiro utilizo o tail para recuperar a última linha do log
- Depois utilizo o grep para “filtrar” se a linha e verificar se ela possui o texto que estamos procurando ($text_to_search). Se o texto não for encontrado, a variável fica vazia.
Verificação de pacotes obrigatórios
Neste passo, verifico se o pacote tar está instalado.
tar_exists=$(dpkg -l | grep -c "tar archiving")
A lógica aqui é bem semelhante a do passo anterior:
- Listo os pacotes instalados (dpkg -l);
- Procuro pelo texto “tar archiving” na lista (grep -c “tar archiving”). A diferença é que o argumento -c do grep vai retornar o número de ocorrências. Sendo assim, se a variável tar_exists for igual a zero, o pacote não está instalado.
Esta parte é meio que um preciosismo meu. Não acho que alguém vai utilizando uma instalação do linux sem o pacote tar, mas ok…
Criando funções auxiliares
Para organizar as coisas, criei duas funções auxiliares:
add_line_to_log() {
echo "[$(date +"%T")] [Backup thread/INFO]: $1" >> $latest_log
}
A função acima adiciona um texto no log atual (latest.log) com timestamp e o indicador de que é o serviço de backup (Backup thread/INFO)
A segunda:
remove_old_backups() {
find $minecraft_folder/$archives_folder/$world_name* -mtime +$max_backup_days -exec rm {} \;
}
Esta função remove os backups antigos. Expliquei ela com detalhes no post “Apagando arquivos com mais de X dias (Linux/Bash)”.
Criando parte de execução do script
A primeira parte da execução é verificar se o pacote tar está instalado. Para isso, utilizo a variável tar_exists (criada anteriormente:
# Pre backup...
if [[ $tar_exists = 0 ]]; then
echo "ERROR: Tar package isnt installed! We need that..."
echo "Try: apt-get install tar"
exit -1
fi
Se ela for igual a zero, o pacote não está instalado e o script é encerrado.
Agora verifico se a variável last_log_line está vazia. Se estiver, a última linha do log não possuir o texto “left the game”, não está na hora de fazer backup. Esta verificação fica assim:
# Backup routine...
if [[ "$last_log_line" = "" ]]; then
# Probably somebody has played or is playing...
echo "Someone is playing. Maybe later..."
else
# Assuming the server is empty...
# Someone has left and nothing else happened. It's safe to make a backup...probably.
echo "Server empty. Backing stuff up..."
add_line_to_log "Automatic backup in progress..."
# Creates the archive
tar --exclude="./*.log" --exclude="./$logs_folder/*.log" --exclude="./$logs_folder/*.log.gz" -zcvf "$backup_file" "$backup_source_files"
# Removing old backups
remove_old_backups
# Adding another line to the log, to show everythings OK.
add_line_to_log "Automatic backup finished successfully!"
fi
A clausula else é onde ocorrerá o backup.
Explicação para os comandos que são executados:
add_line_to_log "Automatic backup in progress..."
Adiciona uma linha no log atual (latest.log), informando que o backup automático está sendo feito.
tar --exclude="./*.log" --exclude="./$logs_folder/*.log" --exclude="./$logs_folder/*.log.gz" -zcvf "$backup_file" "$backup_source_files"
O comando acima cria o arquivo de backup. Como ele está com vários argumentos, vou detalhar melhor este comando:
- –exclude="***": Tudo que for indicado nestes argumentos é ignorado na hora de criar o arquivo. Sendo assim, estou excluindo os logs dos arquivos de backup.
- -zcvf: Cada uma destas letras representa uma configuração..
z: Compacta o arquivo utilizando gzip;
c: Cria arquivo (em oposição ao x, que extrai o conteúdo de um arquivo compactado)
v: Mostra o progresso da operação. Se for omitido, o arquivo vai ser criado “silenciosamente”
f: Indica que será especificado um nome para o arquivo compactado que está sendo criado.
Os próximos dois argumentos são, respectivamente, o nome do arquivo que será criado e o local onde estão os arquivos que serão incluídos no backup.
remove_old_backups
Chama a função criada anteriormente, que vai apagar os backups que tem mais de 14 dias.
add_line_to_log "Automatic backup finished successfully!"
Adiciona outra linha no arquivo de log, informando que o backup foi feito com sucesso.
Se o script passar deste ponto, encerro a execução retornando o código de sucesso:
# OK
exit 0
O script completo está no meu Github.
Automatizando o backup
O script está feito, mas ele ainda não está sendo executando a automaticamente, ou seja, o “fazedor de backups” existe, ele só não é automático… ainda.
Supondo que você tenha salvado o script no caminho /scripts/backcraft.sh
A primeira coisa que você tem que fazer é marcar este script como executável com o comando abaixo:
chmod +x /scripts/backcraft.sh
Agora temos que editar o crontab para inserir este novo job com o comando:
crontab -e
Adicione a seguinte linha ao crontab:
0 */6 * * * /script/backcraft.sh
Salve as alterações e pronto! Backup automatizado!
Espero ter ajudado!