Qual é a melhor maneira de programar um comando para executar, assegurando que um conjunto anterior de comandos foi concluído?

2

Ou seja, eu preciso girar as pastas de backup. Eu tenho muitas máquinas em um cronograma para rsync para uma única máquina de backup. Embora eu programe os backups para começar no final da noite e agendar uma rotação de pasta (para tornar a pasta day0 se tornar day1, começando com a mais antiga) no final da manhã do dia seguinte (fornecendo, digamos, 10 horas para os backups serem concluídos) , Gostaria de poder garantir que todos os backups foram concluídos antes de permitir que a rotação comece, em vez de fazer uma suposição (porque, se eu girar as pastas enquanto um backup estiver em andamento, meu backup estará impreciso).

Isso seria trivial para uma única máquina, mas, para vários, espero que alguém conheça o melhor método ... Posso pensar em alguns, mas prefiro não ter que 'experimentar' em sistemas em execução:

Cada backup cria um carimbo de conclusão e executa o script de rotação a cada poucos minutos após um determinado tempo, verificando se ele não foi executado com êxito e se todos os carimbos são atuais (mais antigos que o carimbo do script de rotação anterior)?

Tenha cada backup mv seu rsync anterior em uma pasta em andamento, rsync, em seguida, mv de volta ao dia0, então a rotação apenas pula esse backup se ele não estiver completo?

Basta viver com backups potencialmente imprecisos?

    
por user1274569 16.03.2012 / 18:44

4 respostas

5

Eu provavelmente escreveria um arquivo de conclusão no servidor central que inclua a data e o nome do host; você poderia usar isso:

#!/bin/bash
# when each backup completes, write a completion file:
ssh user@central-server "touch /path/to/completion-files/$HOST-$(date +%F).complete"

E no servidor central:

#!/bin/bash
# on the central server, run this before attempting folder rotation
for h in (list of hosts); do
  if [[ -e "/path/to/completion-files/$h-$(date +%F)" ]]; 
    then # do your thing
  fi
done
    
por 16.03.2012 / 18:54
1

Para atacar o caso mais geral, que é " Qual é a melhor maneira de agendar um comando para executar, assegurando que um conjunto anterior de comandos tenha sido concluído? "

você precisa executar um comando e testar o sucesso (código de saída) e, em seguida, agendar o comando usando o agendador do sistema (normalmente at ). Por exemplo:

 #!/bin/bash
 rsync "${opts[@]}" "$source" "$dest"
 if [[ $? -eq 0 ]]; then
   at now+10hours <<<"~jdoe/bin/rotatefolders.sh"
 fi

Eu assumi aqui que seu roteiro de rotação de pasta foi nomeado rotatefolders.sh em bin na pasta pessoal do jdoe.

    
por 16.03.2012 / 19:08
0

Como você está usando o rsync, presumo que você faça isso por meio de um ssh-tunnel. Se assim for, você tem ssh no lugar também.

Em vez de um loop de espera ocupado, é melhor usar a sinalização quando o trabalho rsync terminar.

O "sinal" pode acionar o log-rotate no sistema backup.server - seja iniciando diretamente o logrotate, seja iniciando-o indiretamente (via sudo ou ssh-key).

    
por 16.03.2012 / 22:11
-1

Você pode usar o arquivo pid:

PID_FILE="/path/to/pid.pid"   
    if [ -f $PID_FILE ]
    then
            OLD_PID='cat $PID_FILE'
            RUNNING='ps aux |grep $OLD_PID|grep -v grep|wc -l'
            if [ $RUNNING -gt 0 ]
            then
                    echo "WARNING PROGRAM already running"
                    exit 0
            else
                    echo "PID file exists but program is not running. Overriding PID file"
            fi
    fi
    echo $$ > $PID_FILE
    trap "rm -f $PID_FILE; exit" INT TERM EXIT

Compartilhando o arquivo pid, você garantirá que B não será executado até que A termine e o contrário também.

    
por 16.03.2012 / 21:06