Eu faço algo semelhante com rsync
backups [em disco] e encontrei o mesmo problema devido a um daemon que atualiza arquivos enquanto o backup está em execução.
Ao contrário de muitos programas, o rsync tem muitos códigos de erro diferentes [Veja a parte inferior da página de manual]. De interesse são dois:
23 -- partial transfer due to error
24 -- partial transfer due to vanished source files
Quando o rsync está fazendo uma transferência e encontra uma dessas situações, ele não pára imediatamente. Ele salta e continua com os arquivos que ele pode transferir. No final, apresenta o código de retorno.
Portanto, se você receber o erro 23/24, execute novamente o rsync. As execuções subseqüentes serão muito mais rápidas, geralmente apenas transferindo os arquivos ausentes da execução anterior. Eventualmente, você terá [ou deverá obter] uma corrida limpa.
Quanto a ser atômico, eu uso um diretório "tmp" durante a transferência. Então, quando o rsync run estiver limpo, eu o renomeio [atomicamente] para <date>
Eu também uso a opção --link-dest
, mas uso isso para manter backups delta (por exemplo, --link-dest=yesterday
para diárias)
Embora eu não tenha usado eu mesmo, o --partial-dir=DIR
pode impedir que os arquivos ocultos atravancem o diretório de backup. Certifique-se de que o DIR esteja no mesmo sistema de arquivos que seu diretório de backup, para que as renomeações sejam atômicas
Enquanto faço isso em perl, escrevi um script que resume o que venho dizendo com um pouco mais de detalhe / precisão para sua situação particular. Está na sintaxe tcsh-like, [não testada e um pouco difícil], mas trate-a como pseudo-código para escrever seu próprio script bash
, perl
, python
como você escolher. Observe que ele não tem limite para novas tentativas, mas você pode adicioná-lo com bastante facilidade, de acordo com seus desejos.
#!/bin/tcsh -f
# repo_backup -- backup repos even if they change
#
# use_tmp -- use temporary destination directory
# use_partial -- use partial directory
# use_delta -- make delta backup
# set remote server name ...
set remote_server="..."
# directory on server for backups
set backup_top="/path_to_backup_top"
set backup_backups="$backup_top/backups"
# set your rsync options ...
set rsync_opts=(...)
# keep partial files from cluttering backup
set server_partial=${remote_server}:$backup_top/partial
if ($use_partial) then
set rsync_opts=($rsync_opts --partial-dir=$server_partial)
endif
# do delta backups
if ($use_delta) then
set latest=('ssh ${remote_server} ls $backup_backups | tail -1')
# get latest
set delta_dir="$backup_backups/$latest"
if ($#latest > 0) then
set rsync_opts=($rsync_opts --link-dest=${remote_server}:$delta_dir)
endif
endif
while (1)
# get list of everything to backup
# set this to whatever you need
cd /local_top_directory
set transfer_list=(.)
# use whatever format you'd like
set date='date +%Y%m%d_%H%M%S'
set server_tmp=${remote_server}:$backup_top/tmp
set server_final=${remote_server}:$backup_backups/$date
if ($use_tmp) then
set server_transfer=$server_tmp
else
set server_transfer=$server_final
endif
# do the transfer
rsync $rsync_opts $transfer_list $server_transfer
set code=$status
# run was clean
if ($code == 0) then
# atomically install backup
if ($use_tmp) then
ssh ${remote_server} mv $backup_top/tmp $backup_backups/$date
endif
break
endif
# partial -- some error
if ($code == 23) then
continue
endif
# partial -- some files disappeared
if ($code == 24) then
continue
endif
echo "fatal error ..."
exit(1)
end