Como posso enfileirar trabalhos de backup com falha ou perdidos, mesmo se o computador estiver inativo ou desligado?

2

Estou pensando em usar o rsync para fazer backup do meu laptop no meu servidor inicial via ssh . Eu quero fazer isso diariamente, então eu pretendo usar crontab . Minha pergunta é: se um trabalho for perdido (digamos que o backup está programado para um horário em que o laptop é desligado), ele será executado assim que possível? ou simplesmente perderá?

    
por Seb 13.02.2016 / 09:51

1 resposta

1

Desde que você solicitou especificamente:

Fila com falha ou falta de trabalhos de backup, mesmo se o computador estiver inativo ou desligado

Ao executar tarefas de backup no servidor , seria relativamente fácil repetir tarefas (com falha na fila), já que podemos assumir que o servidor será o fator "estável". Os backups perdidos em fila de espera podem ser executados roteando o cronjob para um script, criando uma fila sempre que o backup falhar.

Quando as tarefas são executadas no cliente , a história é um pouco diferente. Quando executamos o trabalho em cron , como percebemos que um trabalho falhou? Como o trabalho não foi iniciado se o computador cliente estiver inativo ou desligado, as coisas seriam muito mais complicadas de serem configuradas no cron.

Portanto, se você deseja executar backups agendados, garantindo que trabalhos com falha ou perdidos serão executados na primeira vez, sugiro não usar o cron em todos os .

Configurar backups agendados / enfileirados em um único arquivo

A solução abaixo é relativamente simples de configurar, seguindo as etapas abaixo:

  1. Grave e teste um comando rsync backup. Use grsync se você não tiver certeza sobre como fazer isso.
  2. Copie o script abaixo em um arquivo vazio, digite o nome (por exemplo) da tarefa de backup, como:

    backup1.py
    
  3. Na cabeça do script, faça as configurações apropriadas:

    #--- enter the working rsync command below
    rsync = "rsync -r -t --progress -s '/home/jacob/Bureaublad/test2' '/home/jacob/Bureaublad/test1'"
    #--- set backup time interval below in hours/minutes
    interval = [0, 10]
    #--- set message True if you'd like a warning if a job failed (else False)
    message = True
    

    Digite o comando rsync entre aspas duplas , como no exemplo.

    • Salve o script com unique_name.py

É isso. A partir do horário de início do script, os backups serão executados exatamente após cada intervalo. Se o trabalho falhar, ele será enfileirado (repetido uma vez por minuto) até que possa ser executado com êxito. Depois disso, o novo backup é definido na hora exata agendada (próxima).

  • Posteriormente, teste execute o script com o comando:

    python3 /path/to/script.py
    

    Se tudo funcionar bem, adicione-o aos aplicativos de inicialização: Dash > Aplicativos de inicialização > Adicionar. Adicione o comando:

    python3 /path/to/script.py
    

O script

#!/usr/bin/env python3
import subprocess
import time
import os
import datetime

#--- enter the working rsync command below
rsync = "rsync -r -t -s '/home/jacob/Bureaublad/test2' '/home/jacob/Bureaublad/test1'"
#--- set backup time interval below in hours/minutes
interval = [24, 0]
#--- set message True if you'd like a warning if a job failed (else False)
message = True
#--- set the max- size of the logfile below (n- lines)
maxlog = 100

#--- don't change anything below
backup_id = os.path.basename(__file__).split(".")[0]
home = os.environ["HOME"]
datefile = home+"/next_backup_"+backup_id; logfile = home+"/backup_log_"+backup_id
print(datefile, logfile)
interval = (interval[0]*3600)+(interval[1]*60)
failed = False

def failed_message():
    # shows a zenity message if a backup failed
    subprocess.Popen([
        "zenity",
        "--info",
        "--text="+backup_id+" failed\n"+\
        "See "+logfile]) 

def readable_t(sec):
    # converts epoch time to readable date & time
    return datetime.datetime.fromtimestamp(sec).strftime('%Y-%m-%d %H:%M:%S')

def currtime():
    # returns current (epoch) time
    return int(time.strftime("%s"))

def sync(failed):
    # performs the rsync command, on errors: writes to log and shows message
    try:
        subprocess.check_call(["/bin/bash", "-c", rsync])
        set_next(planned, interval, currt)
        return False
    except subprocess.CalledProcessError:
        if failed == False:
            open(logfile, "+a").write(readable_t(planned)+" failed\n")
            if message == True:
                failed_message()
        return True

def next_run():
    # reads current queue file, creates it if it doesn't exist
    try:
        return int(open(datefile).read())
    except FileNotFoundError:
        currt = currtime()
        open(datefile, "wt").write(str(currt))
        return currt

def set_next(lastr, interval, currt):
    # creates the next queue, maintains the log file
    nextrun = lastr
    while nextrun <= currt:
        nextrun += interval
    open(datefile, "wt").write(str(nextrun))
    newline = [readable_t(lastr)+" succesfully finished on "+\
                        readable_t(currtime())+"\n"]
    try:
        limited_lines = open(logfile).readlines()[-maxlog+1:]+newline
    except FileNotFoundError:
        limited_lines = newline
    with open(logfile, "wt") as log:
        for l in limited_lines:
            print("4")
            log.write(l)

while True:
    time.sleep(60)
    planned = next_run(); currt = currtime()
    if currt > planned:
        failed = sync(failed)

Além disso

  • O script mantém um arquivo de log, nomeado após o backupscript.
    O número máximo de linhas, para manter no arquivo de log, pode ser definido na cabeça do script:

    #--- set the max- size of the logfile below (n- lines)
    maxlog = 50
    

    Um exemplo

    Noexemploabaixo,oscriptédefinidoparabackupacadacincominutos,apartirdas11:10am.

    • Osdoisprimeiros(11:10,11:15)sãorealizadoscomsucesso
    • Oterceiro(planejado11:20)falha,devidoaofatodequeolaptopdorme.Otrabalhoéenfileiradoeexecutadoligeiramenteatrasado.Otrabalhoterminaàs11:27,opróximobackupagendadoéexecutadoàs10:30
    • Emseguida,otrabalhoagendadopara11:35falhadevidoaofatodeoservidornãoestardisponível.Sevocêdefinirmessage=True:

    • Otrabalhoéenfileiradoeexecutadocomêxitomaistarde,às11:41:44

    eassimpordiante

Comoredefinirahoradeiníciodobackup?

Bastaexcluiroarquivodafilanoseudiretóriopessoaldatarefadebackupcorrespondente(começandocomnext_backup_).Ahoraatualseráanovahoradeiníciodociclo.

Comofuncionasobocapô

  • Quandooscriptéiniciado,oprimeirobackupécriado(apartirdeumminutoapartirdainicializaçãodoscript).
  • Quandoatarefaéconcluída,oscriptcriaumarquivodefila,programadonahora(inicial)dotrabalhoconcluído+ointervalodebackup.
  • Umavezporminuto,oscriptverificaseoarquivodafilaestá"com o passar do tempo", comparando a hora atual com a hora da fila. Nesse caso, o script executa a tarefa de backup, cria a nova fila e assim por diante.

    O que acontece se o laptop (cliente) estiver desligado?
    Em seguida, o arquivo de fila criado mais recente não é atualizado (sobrescrito) pelo script, portanto, ele executará o backup atrasado na primeira vez após a inicialização (ou ativação) do computador.

    Como está a próxima fila de backups criada depois disso?
    O próximo backup é sempre calculado em etapas inteiras do intervalo de backup e sempre estará "em fase". Em outras palavras; se o primeiro backup tiver sido feito às 12:00 e você definir o intervalo como [24, 0] , o próximo backup sempre será enfileirado em 12:00 do dia seguinte.

Vários trabalhos de backup?

O script dura a maior parte do tempo. Se não, só olha para o arquivo da fila uma vez por minuto. Sinceramente significa nada para o seu sistema, é muito bem possível executar várias tarefas de backup, cada uma com seu próprio log & arquivo de fila, ao mesmo tempo. Como os arquivos de log e de filas são nomeados de acordo com o nome do script, tudo o que você precisa fazer é dar a cada um dos scripts um nome exclusivo

    
por Jacob Vlijm 16.02.2016 / 11:53