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!
Latest posts by Breno RdV (see all)
- O que é Metaclass e como ela funciona. (#python #dev #metaclass) - janeiro 11, 2023
- Entenda a mágica dos Generators. (#python, #dev, #generator, #iterator) - dezembro 28, 2022
- Ordenando um DataFrame por múltiplas colunas. (#python #pandas #jupyter #dev #data) - agosto 3, 2022