Como usar o Inotify e o RSYNC para criar um sistema de backup ao vivo

Como usar o Inotify e o RSYNC para criar um sistema de backup ao vivo

Por que você deve usar scripts de bash para executar sincronizações e backups de pastas?

Bash é de longe o intérprete de linguagem de comando compatível com SH mais popular e usada. Hoje você pode encontrar Bash em quase todos os lugares, incluindo o Microsoft Windows com o novo subsistema Windows para Linux. Praticamente toda a distribuição GNU/Linux vem com Bash como o shell padrão. O mesmo se aplica ao macOS e a outros sistemas operacionais do tipo Unix.

Bash não é apenas um idioma de comando; Como outras conchas Unix, Bash é uma linguagem de programação e um intérprete de comando. Tecnicamente falando, o lado de programação de um shell fornece às habilidades e recursos do usuário para combinar utilitários de sistema ou shell em um arquivo. O usuário pode criar comandos apenas combinando comandos em um arquivo de texto; Esses tipos especiais de arquivo de texto que incluem uma coleção de comandos são chamados scripts de shell e, quando esses arquivos recebem permissão para executar, o intérprete de shell os vê como um único comando.

A vantagem de um script bash é que você pode usar as ferramentas da linha de comando diretamente dentro dele sem a necessidade de bibliotecas externas de importação ou origem. Essas ferramentas de linha de comando e utilitários internos são poderosos e podem interagir diretamente com o sistema operacional sem compilação ou intérpretes adicionais; geralmente utilitários principais e interfaces da linha de comando, como Awk, Xargs, encontrar, e grep, pode ter um desempenho muito melhor do que usar scripts python e suas bibliotecas, por exemplo. Não é difícil encontrar pessoas fazendo uma análise avançada de dados usando apenas scripts bash e utilitários internos da GNU. Outros afirmam que esse tipo de abordagem pode ser 235 x mais rápido que um cluster Hadoop - o que não é tão difícil de acreditar, considerando algumas monstruosidades em agrupamento que você pode encontrar hoje em dia apenas para se adequar aos designs de software ruins.

Nesse assunto, sempre surge uma pergunta: se Bash é tão poderoso, por que não usá -la para automatizar todas as coisas chatas? A sintaxe do Bash é simples e pragmática: oferece a capacidade de combinar programas para automatizar tarefas comuns. No entanto, quando o script precisa lidar com várias condições ou acumular muitos propósitos, é hora de considerar uma linguagem de programação mais robusta, como C ou outros idiomas de script, onde Python e Perl são bons exemplos.

Por outro lado, os scripts de bash são muito bons para tarefas únicas, como a intenção deste artigo: combinar utilitários com recursos para verificar se há alterações em uma pasta específica e depois sincronizar seus arquivos. Um script bash pode se adequar perfeitamente a esta tarefa.

O que você precisa para realizar sincronização ou autobackups?

Há uma grande lista de métodos diferentes para sincronizar pastas e arquivos. O número de aplicativos que podem ser usados ​​para realizar essa tarefa simples é vasta, e alguns deles são soluções de terceiros. No entanto, Este artigo mostra uma maneira mais elegante de realizar o mesmo usando apenas Inotifywait e rsync em um script de bash. Em geral, esta solução será leve, barata e, por que não dizer, mais segura. Em essência, apenas inotificar-se-tools, rsync e um loop de tempo são obrigados a concluir esta missão.

Como usar o InotifyWait para autobacks e sincronizações?

Inotifywait usa a API inotify para aguardar mudanças nos arquivos. Este comando foi especialmente projetado para ser usado em scripts de shell. Uma característica poderosa de Inotifywait é verificar se há alterações continuamente; Assim que novos eventos ocorrem, Inotifywait imprime as modificações e saídas.

Inotifywait Fornece duas opções muito interessantes para sincronização de pastas ou backups em tempo real. O primeiro é o -r, -recursivo opção; Como o nome indica, essa bandeira observa as profundezas dos subdiretos ilimitados de um diretório específico passado como argumentos para Inotifywait, excluindo links simbólicos.

O -e, -evento Flag fornece outro recurso interessante. Esta opção requer uma lista de eventos predefinidos. A documentação do Inotify-Tool lista mais de 15 eventos para Inotifywait; Mas um sistema simples de backup e sincronização requer apenas o Excluir, Modificar e Criar Eventos.
O comando a seguir é um bom exemplo de um cenário do mundo real:

$ inotifywait -r -e modificar, criar, excluir/home/userdir/documentos

Nesse caso, o comando aguarda mudanças - modificações, criações de arquivos ou pastas ou exclusões de qualquer tipo - no fictício /home/userdir/documentos diretório. Assim que o usuário faz qualquer alteração, Inotifywait produz a modificação e saída.

Supondo que você crie um novo arquivo chamado novo arquivo dentro de Documentos pasta enquanto a Inotifywait está monitorando isso. Depois que o comando detectar a criação de arquivos, ele é produzido

Documentos/ Crie NewFile

Em outras palavras, Inotifywait impressões onde a modificação ocorre, que tipo de alterações fez e o nome do arquivo ou pasta que foi alterado.

Examinando o status de saída de Inotifywait Quando ocorre uma alteração, você vê um status de 0-Exit que significa uma execução bem-sucedida. Esta situação é perfeita para um script de shell porque um status de saída pode ser usado como uma condição verdadeira ou falsa.

Consequentemente, a primeira etapa do script está concluída: encontrar um utilitário que aguarde mudanças nos diretórios. O segundo é procurar um utilitário capaz de sincronizar dois diretórios e rsync é um candidato perfeito.

Como usar o RSYNC para Autobackups?

rsync é uma aplicação poderosa. Você pode escrever um livro descrevendo tudo o que pode fazer com este utilitário versátil. Tecnicamente falando, rsync nada mais é do que uma ferramenta de cobrança de arquivos, uma espécie de cp comando com esteróides e poderes especiais, como arquivos de transferência seguros. O uso de rsync Neste script é mais modesto, mas não menos elegante.

O principal objetivo é encontrar uma maneira de:

  • Recorrer em diretórios;
  • Copiar links simbólicos como links simbólicos;
  • Preservar permissões, propriedade, grupos, tempo de modificação, dispositivos e arquivos especiais;
  • Forneça detalhes adicionais, saída detalhada - portanto, é possível criar um arquivo de log se necessário;
  • Compactar arquivos durante a transferência pela otimização.

O rsync A documentação está bem escrita; Verificando o resumo das opções disponíveis, você pode selecionar facilmente o -Avz bandeiras como a melhor escolha. Um uso simples parece o seguinte:

rsync -avz /

É importante colocar uma barra após a pasta de origem. Pelo contrário, rsync Copia toda a pasta de origem (inclusive ela) para a pasta de destino.

Por exemplo, se você criar duas pastas, uma chamada OriginFolder e o outro pasta de destino, fazer rsync Envie para o segundo todas as alterações feitas no primeiro, use o comando subsequente:

$ rsync -Avz Orígenes/ DestinationFolder

Depois de criar um novo arquivo chamado novo arquivo, rsync imprime algo como:

Enviando lista de arquivos incremental
./
novo arquivo
Enviado 101 bytes recebidos 38 bytes 278.00 bytes/s
O tamanho total é 0 aceleração é 0.00

Na primeira linha, a diretiva imprime o tipo de processo, uma cópia incremental; Isso significa que o rsync usa seus recursos de compressões para aumentar apenas o arquivo e não alterar todo o arquivo. Como é a primeira vez que o comando é executado, o aplicativo copia o arquivo inteiro; Depois que novas mudanças ocorrem, apenas incrementosos ocorrem. A saída subsequente é o local, o nome do arquivo e os dados de desempenho. Verificando o status de saída do rsync Comando, você recebe um 0-Exit para execução bem-sucedida.

Portanto, existem dois aplicativos importantes para dar suporte neste script: um é capaz de esperar por mudanças e o outro pode criar cópias dessa modificação em tempo real. Aqui, o que está faltando é uma maneira de conectar os dois utilitários de uma maneira que rsync agir assim que Inotifywait percebe qualquer alteração.

Por que precisamos de um pouco de loop?

A solução mais simples para o problema acima é um loop de tempo. Em outras palavras, em cada ocasião Inotifywait existe com sucesso, o script bash precisa ligar rsync para realizar sua incremento; Imediatamente após a cópia ocorrer, o shell precisa voltar ao estado inicial e esperar por uma nova saída do Inotifywait comando. Isso é exatamente o que um loop faz.

Você não precisa de um extenso pano de fundo em programação para escrever um script de basquete. É muito comum encontrar bons administradores de sistemas que não tenham experiência muito limitada com programação. No entanto, Criar scripts funcionais é sempre uma tarefa importante da administração do sistema. A boa notícia é que o conceito por trás de um loop de tempo é fácil de entender.

O diagrama a seguir representa um loop de tempo:

Infinito enquanto diagrama de loop.

A representa o Inotifywait Comando discutido acima e B, rsync. Toda vez A Existe com um status de 0-Exit, o shell o interpreta como verdadeiro; Assim, o loop do tempo permite a execução de B; tão logo B Também sai com sucesso, o comando retorna para A novamente e repete o loop.
Nesse caso, o while loop sempre avalia verdadeiro para A. Tecnicamente, gera um loop infinito, o que é bom para a proposta desse script; Inotifywait será executado recorrente, o que significa que sempre esperará por novas modificações.

Mais formalmente, a sintaxe para uma festa enquanto o loop é:

enquanto
fazer

feito

significa a lista de condições (A) essa necessidade de ser verdadeira; Então, enquanto o loop pode executar o , Permanecendo para o bloco de comandos (B). Se o loop pré-teste A é falso, então o loop while sai sem executar B.

Aqui está como rsync e Inotifywait Os comandos se encaixam dentro do while loop,

Enquanto Inotifywait -r -e modificar, criar, excluir o OrígenesFolder
fazer
rsync -Avz OrígenesFolder/ DestinationFolder
feito

Combinando tudo

Agora é hora de combinar tudo discutido acima para criar um script de shell. A primeira coisa é criar um arquivo vazio e nomeá -lo; como um exemplo, LiveBackup.Bash representa uma boa escolha. É uma boa prática colocar scripts de shell na pasta Bin sob o diretório inicial do usuário, um.k.a. $ Home/Bin.

Depois disso, você pode editar o arquivo no editor de texto de sua escolha. A primeira linha de um script bash é muito importante; É aqui que o script define a diretiva de intérprete, por exemplo:

#! [Opções]

O shebang é esse símbolo estranho com um hash e um ponto de exclamação (#!). Quando o shell carrega o script pela primeira vez, procura esse sinal, pois indica o que o intérprete precisa ser usado para executar o programa. O shebang não é um comentário, e precisa ser colocado no topo do script sem espaços acima.

Você pode deixar a primeira linha vazia e não definir o intérprete. Dessa forma, o shell usa o intérprete padrão para carregar e executar o script, mas não é endossado. A escolha mais apropriada e segura é indicar a diretiva de intérprete da seguinte maneira:

#!/usr/bin/bash

Com a diretiva de intérprete explícita assim, o shell procura o intérprete de bash sob o diretório /usr /bin. Como a tarefa deste script é simples, não há necessidade de especificar mais comandos ou opções. Uma possibilidade mais sofisticada é chamar o intérprete usando o comando Env.

#!/usr/bin/Env Bash

Nesse contexto, o shell procura o comando Bash padrão no ambiente atual. Esse arranjo é útil quando o ambiente do usuário tem personalizações importantes. No entanto, isso pode levar a falhas de segurança em um nível corporativo, uma vez que o shell não puder detectar se o comando Bash sob um ambiente personalizado é ou não é um intérprete seguro.

Ao montar tudo neste momento, o script se parece:

#!/usr/bin/bash
Enquanto Inotifywait -r -e modificar, criar, excluir o OriginFolder
fazer
rsync -Avz OrígenesFolder/ DestinationFolder
feito

Como usar argumentos em um script de bash?

O que separa esse script de uma funcionalidade total é como está definindo a origem e a pasta de destino. Por exemplo, é necessário encontrar uma maneira de mostrar o que são essas pastas. O modo mais rápido para resolver essa pergunta é usar argumentos e variáveis.

Aqui está um exemplo da maneira correta de se referir ao script:

$ ./LiveBackup.Bash/Home/Usuário/Origin/Home/Usuário/Destino

O shell carrega qualquer um desses argumentos digitados após o nome do script e os passa para o carregador de scripts como variáveis. Por exemplo, o diretório /casa/usuário/origem é o primeiro argumento, e você pode acessá -lo dentro do script usando o $ 1. Por isso, $ 2 tem um valor de /Home/Usuário/Destino. Todas essas variáveis ​​posicionais podem ser acessadas usando o sinal de dólar ($) seguido de um número n ($ n), onde n é a posição do argumento em que o script é chamado.

O sinal do dólar ($) tem um significado e implicações muito especiais dentro de scripts de shell; Em outros artigos, será discutido em profundidade. Por enquanto, o quebra -cabeça está quase resolvido.

#!/usr/bin/bash
Enquanto InotifyWait -R -e Modify, crie, exclua $ 1
fazer
rsync -avz $ 1/ $ 2
feito

Observação: para lidar com muitos argumentos usando apenas parâmetros posicionais ($ n) pode rapidamente levar a maus designs e confusão em scripts de shell. Uma maneira mais elegante de resolver esse problema é usar o getopts comando. Este comando também ajuda você a criar alertas de uso indevido, o que pode ser útil quando outros usuários têm acesso ao script. Uma pesquisa rápida na internet pode mostrar diferentes métodos de usar getopts, O que pode melhorar o script atual se você precisar dar mais opções de uso para outros usuários.

Tornando -o executável

Apenas mais uma coisa precisa ser feita agora: fazer o arquivo LiveBackup.Bash executável. Pode ser facilmente realizado com o chmod comando.

Vá para a pasta que contém o script e digite:

$ chmod +x vivebackup.Bash

Em seguida, digite o sinal de pontuação (./) Antes do nome do script. O DOT significa, neste contexto, o diretório atual e a barra define um caminho relativo para o arquivo no diretório atual. Com isso em mente, você também precisa digitar a pasta de origem como o primeiro argumento, seguido pela pasta de destino como a segunda, como:

$ ./LiveBackup.Bash/Home/Usuário/Origin/Home/Usuário/Destino

Como alternativa, você pode chamar os scripts pelo nome, colocando a localização da pasta no caminho do ambiente ou chamando -o de subshell, como:

$ Bash LiveBackup.Bash/Home/Usuário/Origin/Home/Usuário/Destino

A primeira opção é uma escolha segura embora.

Exemplo da vida real

Em um cenário do mundo real, Executando manualmente um script de backup cada vez que você inicializa o sistema, pode ser tedioso. Uma boa escolha é usar um Cronjob ou Timers/serviço unidades com Systemd. Se você tiver muitas pastas diferentes para fazer backup, também pode criar outro script que obtenha LiveBackup.Bash; Assim, o comando precisa ser chamado apenas uma vez em um .serviço unidade. Em outro artigo, esse recurso pode ser discutido em mais detalhes.

Se você estiver usando o subsistema do Windows para Linux, é possível criar uma tarefa básica para executar seu script usando o "Agendador de tarefas" que é acionado pela inicialização do sistema. Para usar um arquivo em lote para ligar para o Bash.exe com uma lista de comandos é uma boa escolha. Você também pode usar um script Visual Basic para iniciar o arquivo em lote em segundo plano.

Como é um script profissional

Aqui está um exemplo de um script projetado pelo autor que pode ler argumentos de linha de comando mais sofisticados.

#!/usr/bin/Env Bash
#
########Omas ########################################D
########Omas ########################################D
#
# Script: SyncFolder.Bash
# Autor: Diego Aurino da Silva
# Data: 16 de fevereiro de 2018
# Rev: 1.0
# Licença: MIT (https: // github.com/diegoaurino/Bashscripts/blob/mestre/licença)
#
# Plataforma: WSL ou GNU/Linux
#
# Objetivo: pequeno script para sincronizar as mudanças da esquerda para a direita de duas pastas
# em WSL ou GNU/Linux (requer ferramentas inotificadas)
#
########Omas ########################################D
########Omas ########################################D
#################
# CONFIGURAÇÕES GERAIS
#################
Bold = $ (Tput Bold)
Normal = $ (tput sgr0)
Orígene = ""
destino = ""
#################
# Seção de opções
#################
Se [$# -EQ 0]
então
printf "\ n%s \ t \ t%s \ n \ n" "use $ Bold -h $ normal para obter ajuda."
saída 1
outro
enquanto getopts ": h" opção
fazer
caso $ opção em
h)
printf "\ n%s \ t \ t%s \ n \ n" "Uso: ./SyncFolder.Bash $ Bold/Orígenes/pasta $ Normal -o $ Bold/destino/pasta $ Normal "
saída 0
;;
\? )
printf "\ n%s \ n \ n" "$ BOLD opção inválida para $ normal $ (nome da base $ 0)" 1> & 2
saída 1
;;
ESAC
feito
turno $ ((optind -1))
Orígenes = $ 1
mudança
enquanto getopts ": o:" opção
fazer
caso $ opção em
o)
destino = $ optarg
printf "\ n%s \ n \ n" "As seguintes pastas serão sincronizadas com esquerda-direita:"
printf "\ torigen: \ t \ t \ t%s \ n" "$ BOLD $ ORIGEN $ Normal"
printf "\ tDestination: \ t \ t%s \ n \ n" "$ BOLD $ destino $ normal"
;;
\? )
printf "\ n%s \ n \ n" "$ BOLD opção inválida para $ normal $ (nome da base $ 0): -$ optarg."1> & 2
saída 1
;;
:)
printf "\ n%s \ n \ n" "$ BOLD a opção $ normal -$ optarg requer um diretório como argumento."1> & 2
saída 1
;;
*)
printf "\ n%s \ n \ n" "$ BOLD Opção Unkown para $ Normal $ (nome da base $ 0): -$ optarg."1> & 2
saída 1
;;
ESAC
feito
turno $ ((optind -1))
fi
#################
# Seção de sincronização
#################
Enquanto Inotifywait -r -e modifique, crie, exclua $ ORIGENS
fazer
rsync -avz $ origen/ $ Destination - -Delete --filter = 'P .git '
feito

Desafios

Como um desafio, tente projetar mais duas versões do script atual. O primeiro precisa imprimir um arquivo de log que armazena todas as alterações encontradas pelo Inotifywait comando e toda incrementação feita por rsync. O segundo desafio é criar um sistema de sincronização de duas direção usando apenas um loop de tempo como o script anterior. Um conselho: É mais fácil do que parece.

Você pode compartilhar suas descobertas ou perguntas no Twitter @linuxhint