Areas: Principal | Apache | DNS | FreeSWAN | giFT | LDAP | Mutt | Postfix | Sincronia | Vim | VNC

Sincronia/Réplica de Arquivos com o Unison

Deives Michellis "thefallen"
Revisão: $Id: Unison-básico.t2t,v 1.2 2004/07/09 19:19:24 thefallen Exp $



Introdução

Você provavelmente já ouviu muita gente falar de réplica disso, réplica daquilo, sincronização, etc. Talvez até já tenha brincado com CodaFS, ou InterMezzo, ou mesmo EVMS ou DRBD. Todos esses são implementações no kernel, e requerem uma configuração um tanto quanto complexa, e muitas vezes não são flexíveis o suficiente ou não tem alguma caracteristica especifica pra comportar a sua aplicação. Ou podem ser simplesmente um "overkill", como dizem os gringos.

Aqui vai uma dica de um sistema de réplica simplissimo de montar e configurar, trabalha sobre SSH, e pode mesmo sincronizar um diretório entre o Windows e um Unix.

1. O que é

O Unison trata-se de uma melhoria ou aprimoramento no algorítmo RSYNC. O rsync trabalha com sincronização de um lado apenas, ou seja, um "mestre" e todos os outros são "escravos", que simplesmente refletem as alterações do nó mestre. O Unison tenta fazer a sincronização de ambos os lados, conciliando as alterações conflitantes.

O Unison pode usar como transporte uma conexão TCP/IP normal (com o unison rodando em modo daemon ou via inetd), um compartilhamento NFS (ou SAMBA, ou qualquér diretório montado do sistema) ou conexões RSH ou SSH.

Toda a sincronia é feita em ambiente de usuários, não sendo necessário nenhuma alteração ou configuração do kernel.

O Unison pode ser obtido do site http://www.cis.upenn.edu/~bcpierce/unison/ .

2. Como funciona

O Unison primeiramente levanta uma lista de sincronia de arquivos do diretório especificado e solicita que o Unison do "outro lado" faça o mesmo.

Se houverem novos arquivos/diretórios de qualquér dos lados, o Unison réplica essas diferenças. Quando há 2 arquivos conflitantes, o Unison permite que se escolham diversos cursos de ação: pode-se forçar um servidor a ser o mestre (quando conflitar, use a cópia do servidor X), ou pode-se escolher o mais recente como mestre, ou pode-se fazer uma mistura ("merge") entre os 2 arquivos conflitantes (com o diff, por exemplo).

O esquema de "merge" para arquivos conflitantes requere que você faça scripts para juntar os arquivos.

Se arquivos/diretórios forem removidos, o Unison réplica essas alterações também.

3. Aplicações Práticas

Aqui vão algumas idéias de como usar o mecanismo de réplica:

Backups - Mantenha um servidor de reserva com os dados do servidor principal espelhados nele.

Sincronizar Home Directories - Manter seu Home Directory em casa sincronizado com o seu Home Directory no Serviço e vice-versa. Nada mais de ter que fazer SSH pra ver aquele texto que você esqueceu em casa :)

Mas espere um pouco. Se eu posso fazer a réplica de alterações para ambos os lados, por que manter um servidor de reserva? Por que não deixa-lo rodando em paralelo com outro server, já que eles vão sincronizar alterações/novos arquivos?

É aqui que o Unison fica realmente interessante. Com ele podemos montar aplicações de alta disponibilidade sem precisar mexer no kernel com réplicações que nem sempre funcionam. Se eu fizer isso distribuído, ainda posso aumentar o desempenho da aplicação por distribuir a carga.

Esse tipo de sincronia funciona maravilhosamente bem com caixas de correio Maildir. No ambiente de email não há necessidade de sincronia imediata de mensagens (podemos sincronizar de 1 em 1 minuto ou mais, por exemplo, que não haverá problemas com as aplicações)

Outras aplicações que trabalhem com arquivos independentes (que não sejam alterados frequentemente e nem simultaneamente) também poderao tirar muito benefício dessa sincronização sem se preocupar com merges de arquivos.

4. Mãos a obra!

Chega de bla bla bla e vamos partir pra parte prática.

4.1. Instalando

No site do Unison já existem versões pré-compiladas estáticas do Unison. Pegue a versão em modo texto (unison.linux-static-textui) e copie para o /usr/bi/nunison .

Se quiser compila-lo você mesmo, vai necessitar do compilador Objective Caml (versão 3.04 ou superior).

4.2. Configurando

Vamos primeiro configurar o Unison pra replicar o Home Directory e depois para replicar Maildirs de emails.

4.2.1. Replicando o Home Directory

Crie no seu Home Directory o diretório ~/.unison . Agora vamos criar uma configuração chamada "home". O arquivo devera chamar home.prf.

  #~/.unison/home.prf
  # Unison preferences file
  root = /home/thefallen/
  # Dica: SEMPRE coloque // entre o nome da máquina e o diretório a sincronizar
  root = ssh://minha.outra.máquina.com//home/thefallen/
  # Caso seu ssh esteja em outra porta...
  #rshargs = -oPort=2222
  # Diretórios que quero sincronizar
  path = Docs
  path = MyDocs
  path = c
  # Arquivos que não devem ser replicados
  ignore = Name *.log*
  ignore = Name .*
  # diretório que não deve ser replicado
  ignore = Path tmp
  # Não replique diretórios/arquivos que tenham "tmp" no nome
  ignore = Regex .*tmp.*
  # batch == roda sem fazer perguntas; indicado para tarefas cron e similares
  #batch = true
  # encare a cópia mais recente como master; não tente fazer "merge"
  prefer = newer
  # Piloto automatico :)
  auto = true
  # Sincronize a hora de modificação.
  times = true
  log = true
  logfile = /home/thefallen/.unison/réplica.log

Agora digite "unison home" e veja o Unison sincronizando seu Home Directory :)

Você pode usar ssh com autenticação por chave pública, e nem a senha vai precisar digitar :)

4.2.2. Replicando diretórios de email Maildir

Supondo que seu diretório de emails no formato Maildir seja /var/vmail, e que o outro servidor seja 10.10.0.2, e que você esteja usando o Courier IMAPd. Crie o arquivo de configuração maildir.prf dentro do ~/.unison/

  #~/.unison/maildir.prf
  root = /var/vmail/
  # lembre-se: SEMPRE com 2 / depois do nome da máquina
  root = ssh://10.10.0.2//var/vmail/
  # medidas de segurança pra não copiar arquivos temporarios de entrega
  # de mensagem ou do IMAP
  ignore = Name maildirsize
  ignore = Name courier*
  ignore = Path */tmp/*
  # AutoPilot is on :)
  auto = true
  batch = true
  times = true
  # Prefiro a cópia mais recente como master
  prefer = newer
  # se vc quiser que o unison replique donos/owners de arquivo ; precisa do poder do root
  #owner = true

4.2.3. Replicando XYZ

No site do Unison existe uma documentação muito boa (em inglês). Você pode inventar muitas maneiras de aproveitar o sistema de réplicação de arquivos do Unison (lembra do "Neston"? Invente uma!)

4.3. Múltiplos Servidores

O Unison, por natureza, trabalha apenas com réplicação de dados entre 2 máquinas. Para colocar múltiplos servidores na réplicação, você precisar colocar múltiplas replicas entre os servidores (ou manter um dos servidores como um nó "central", e todos vão replicar com ele). O script syncmgr ajuda nessa hora; ele só vai permitir que um servidor sincronize por vez.

4.4. Uma palavra de cautela

Embora o Unison seja preparado para lidar com réplicações simultâneas (você replicaria daqui pra la e eu replicaria de la pra ca os mesmos arquivos), esse recurso não foi exaustivamente testado e convém evitar essa situação. Com alguns scripts, conseguimos evitar essas situações. Veja no próximo item.

4.5. Automatizando as replicas

Você pode por a réplicação pra rodar no cron, se quiser. No entanto, uma coisa me ocorreu. E se uma réplicação demorar mais do que o intervalo do cron e eu iniciar uma réplicação quando a outra ainda estiver rodando (se eu colocar pra sincronizar de 1 em 1 minuto por exemplo)? Já imaginou a bagunça (e uso de CPU e Disco) que isso poderia causar?

Para escaparmos dessa "race-condition", basta mantermos um único processo que faz a rotina de sincroniza-espera-sincroniza-espera... Podemos melhorar ainda mais essa idéia colocando alguns mecanismos básicos de travamento que impedem (ou tentam impedir) que ocorram 2 sincronizações (tanto remotas como locais) de um mesmo perfil de configuração.

4.5.1. cron job

Simplesmente coloque uma tarefa no cron com a seguinte sintaxe:

  */15 * * * * /usr/bin/unison maildir -silent -batch -auto

Se algo acontecer que o unison não consiga resolver, o cron vai lhe enviar a saída do comando por email.

A flag -silent faz com que sejam apresentados apenas erros e a flag -batch diz ao unison pra não perguntar nada ao usuário.

4.5.2. Init service

Você pode também criar uma tarefa no INIT que mantem o serviço de réplicação rodando. Dessa maneira, apenas ocorre 1 sincronização por vez (não há o perigo de "encavalar" como poderia acontecer com o cron) e caso o script caia ou você mate inadvertidamente o script, o INIT o inicia de novo.

De permissão de execução (com chmod 755 remotesync syncmgr) e adicione uma linha parecida com essa no /etc/inittab:

  # /etc/inittab:
  s001:2345:respawn:/bin/su - USUARIO_QUE_DEVERA_REPLICAR -c "/opt/filesync/bin/syncmgr maildir"

Faça um reload no init com o comando "telinit q" ou "init q" e acompanhe os logs do que acontece no /opt/filesync/var/log/.

4.5.3. Processo em background

Se você não gosta da idéia de colocar serviços no INIT, pode simplesmente coloca-lo em background com o auxílio do comando nohup. Bastaria rodar o comando:

  nohup /opt/filesync/bin/syncmgr maildir 1>/dev/null 2>/dev/null 0</dev/null &

Para para-lo, basta mandar um kill -9 no proceso (ou killall -9 syncmgr).

Você pode fazer um script de rc para ele. Segue um exemplo:

  #!/bin/sh
  # /etc/rc.d/rc.unison
  case "$1" in
    start)
      echo -n "Iniciando réplicação UNISON: "

      echo -n " maildir"
      su nobody -c "nohup /opt/filesync/bin/syncmgr maildir \
          1>/dev/null 2>/dev/null 0</dev/null &"

      echo -n " home"
      su thefallen -c "nohup /opt/filesync/bin/syncmgr home \
          1>/dev/null 2>/dev/null 0</dev/null &"

      echo ""
    ;;
    stop)
      echo "Parando réplicação UNISON"
      killall -9 syncmgr 2>/dev/null
    ;;
  esac

4.5.4. syncmgr e remotesync

NOTA - se for utiliza-lo rodando pelo cron, edite o syncmgr e remova a linha que faz o loop

Vamos agora criar o script. Crie o diretório /opt/filesync e os subdiretorios bin, var/log e var/lock. Vamos agora criar 2 scripts no /opt/filesync/bin/:

  #!/bin/sh
  # Arquivo /opt/filesync/bin/syncmgr
  #
  # Copyright (c) 2004, Deives Michellis
  #    All rights reserved.
  #
  #    Redistribution and use in source and binary forms, with or without
  #    modification, are permitted provided that the following conditions are
  #    met:
  #      * Redistributions of source code must retain the above copyright
  #        notice, this list of conditions and the following disclaimer.
  #      * Redistributions in binary form must reproduce the above copyright
  #        notice, this list of conditions and the following disclaimer in
  #        the documentation and/or other materials provided with the
  #        distribution.
  #      * Neither the name of the Deives Michellis nor the names of its
  #        contributors may be used to endorse or promote products derived
  #        from this software without specific prior written permission.
  #
  #    THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  #    "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  #    LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
  #    A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  #    OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
  #    SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
  #    LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
  #    DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
  #    THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
  #    (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
  #    OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
  #
  export PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin

  DATADIR=/opt/filesync/
  # Qto tempo esperar se a sincronização já estiver acontecendo (remotamente)
  # Numero de vezes q a verificação de sincronia remota é feita
  MAXWAIT=12
  # Quanto tempo espera em cada verificação
  SLEEP=10
  # De quanto em quanto tempo tentar sincronizar
  INTERVAL=180
  # quem informar caso "algo aconteca"
  EMAILADDR=seu_email@aqui.com

  # Verificação do nome do profile
  SYNCNAME=`echo $1 | sed -e 's/[^a-z0-9]//gi'`
  if [ "$SYNCNAME" = "" ]; then
    echo "Invalid Profile name"
    exit 1
  fi

  trap "rm -f $DATADIR/var/lock/$SYNCNAME/$$ $DATADIR/var/log/réplica.$$.log" 0 1 9 15

  if [ ! -d $DATADIR/var/lock/$SYNCNAME ]; then
    mkdir -p  $DATADIR/var/lock/$SYNCNAME/
  fi

  # Main loop - remova a linha do "while" se for usa-lo via cron
  while true; do
    COUNT=0
    while [ `ls -1 $DATADIR/var/lock/$SYNCNAME/ 2>/dev/null| wc -l ` -gt 0 ]; do
      if [ $COUNT -ge $MAXWAIT ]; then
        break
      fi
      COUNT=`expr $COUNT + 1`
      sleep $SLEEP
    done

    touch $DATADIR/var/lock/$SYNCNAME/$$
    echo "Subject: REPLICA LOG $SYNCNAME
  Date: `date -R`
  From: Unison Sync Manager <$EMAILADDR>
  " > $DATADIR/var/log/réplica.$$.log
    unison $SYNCNAME -servercmd "$DATADIR/bin/remotesync $SYNCNAME" -dumbtty \
      -batch >>$DATADIR/var/log/réplica.$$.log 2>>$DATADIR/var/log/eplica.$$.log

    RETVAL=$?
    rm -f $DATADIR/var/lock/$SYNCNAME/$$

    if [ $RETVAL -eq 2 ]; then
      /usr/sbin/sendmail -f MAILER-DAEMON -- $EMAILADDR \
        < $DATADIR/var/log/réplica.$$.log
    fi

    sleep $INTERVAL
  # Fim do Main loop - remova o "done" se for usa-lo via cron
  done


  ----------------------------------

  #!/bin/sh
  # Arquivo /opt/filesync/bin/remotesync
  #

  export PATH=/usr/local/sbin:/usr/sbin:/sbin:/usr/local/bin:/usr/bin:/bin

  DATADIR=/opt/filesync/
  MAXWAIT=12
  SLEEP=10

  SYNCNAME=`echo $1 | sed -e 's/[^a-z0-9]//gi'`

  trap "rm -f $DATADIR/var/lock/$SYNCNAME/$$" 0 1 9 11 15

  if [ ! -d $DATADIR/var/lock/$SYNCNAME ]; then                                                                                             mkdir -p  $DATADIR/var/lock/$SYNCNAME/
  fi
  COUNT=0
  while [ `ls -1 $DATADIR/var/lock/$SYNCNAME/ 2>/dev/null| wc -l ` -gt 0 ]; do
    if [ $COUNT -ge $MAXWAIT ]; then
      break
    fi
    COUNT=`expr $COUNT + 1`
    sleep $SLEEP
  done

  touch $DATADIR/var/lock/$SYNCNAME/$$
  unison -server
  rm -f $DATADIR/var/lock/$SYNCNAME/$$

Esse script atrasa por 2 minutos (no máximo) a réplicação se ela já estiver acontecendo "do outro lado".

Convém que você faça a primeira réplicação manualmente, sem o modo batch. Caso você tenha configurado algo errado, vai perceber :) .

5. Conclusão

Como pudemos observar, o Unison é um software rico em recursos, sendo que apenas uma pequena parte deles foi abordada aqui.

Quando descobri esse software fiquei bastante impressionado, especialmente com o fato dele ser completamente em ambiente de usuário, inclusive com transporte SSH para as comunicações.

Já tenho o unison rodando aqui há algumas semanas, e até agora não houve nenhum problema, e a performance das réplicações foi agradavelmente surpreendente.

Pra quem gostou da idéia, vale explorar suas opções; o site possui uma documentação muito boa e explicativa.

Sobre o autor

Deives Michellis "thefallen" é Tecnologo em Processamento de Dados pela FATEC e Gerente de Desenvolvimento de Soluções Linux do Grup o GEO. Também nerd de carteirinha e ativista linux nas horas vagas.

Ultima Revisão: Fri Sep 10 12:13:17 2004

Criado com o txt2tags

--- html... --- html... wrote /dev/stdout

A menos que especificado de outra maneira, todos os documentos e textos sao protegidos sob licenca BSD - Veja a licenca para mais detalhes
Leia tambem sobre o motivo de uso de licencas em documentacao.