Se o Apache estiver escrevendo um arquivo de algum tipo em um local e não tiver concluído a gravação e depois rsync
entrar em ação, rsync
copiará o que estiver lá.
Ou seja, se o Apache estiver lidando com um arquivo de 5 MB, apenas 2 MB são gravados e rsync
entram em ação, o arquivo parcial de 2 MB será copiado. Portanto, esse arquivo parece estar "corrompido" no servidor de destino.
Dependendo do tamanho dos arquivos que você está usando, você pode usar a --inplace
opção rsync
para fazer o seguinte:
Esta opção altera a maneira como o rsync transfere um arquivo quando os dados do arquivo precisam ser atualizados: em vez do método padrão de criar uma nova cópia do arquivo e movê-lo para o lugar quando estiver concluído, o rsync grava os dados atualizados diretamente no destino Arquivo.
A vantagem disso é que, se um arquivo de 5 MB tiver apenas 2 MB copiados na primeira execução, a próxima será recuperada com 2 MB e continuará a copiar o arquivo até que os 5 MB completos estejam no local.
O negativo é que isso pode criar uma situação em que alguém está acessando o servidor da web enquanto um arquivo está sendo copiado e então eles vêem um arquivo parcial. Na minha opinião, rsync
funciona melhor em seu comportamento padrão de armazenar em cache um arquivo "invisível" e depois movê-lo para o lugar imediatamente. Mas --inplace
é bom para cenários em que arquivos grandes e restrições de largura de banda podem impedir que um arquivo grande seja facilmente copiado da estaca zero.
Disse que você afirma isso; ênfase é minha:
A cada cinco minutos , o cron roda o rsync…
Então, suponho que você tenha algum script bash para gerenciar esse trabalho cron? Bem, a coisa é rsync
inteligente o suficiente para copiar apenas os arquivos que precisam ser copiados. E se você tem um script que é executado a cada 5 minutos, parece que você está tentando evitar rsync
entrar um no outro se for mais rápido. Ou seja, se você executá-lo a cada minuto, existe o risco de que um ou mais rsync
processos ainda estejam em execução devido ao tamanho do arquivo ou à velocidade da rede e o próximo processo estará apenas em concorrência com ele; uma condição de corrida.
Uma maneira de evitar isso é agrupar todo o rsync
comando em um script bash que verifique se há um bloqueio de arquivo; abaixo está uma estrutura de script bash padrão que eu uso para casos como este.
Observe que algumas pessoas recomendam o uso, flock
mas como flock
não está instalado em alguns sistemas que eu uso - e eu pulo muito entre o Ubuntu (que possui) e o Mac OS X (que não possui) - eu uso essa estrutura simples sem nenhum problema real:
LOCK_NAME="MY_GREAT_BASH_SCRIPT"
LOCK_DIR='/tmp/'${LOCK_NAME}.lock
PID_FILE=${LOCK_DIR}'/'${LOCK_NAME}'.pid'
if mkdir ${LOCK_DIR} 2>/dev/null; then
# If the ${LOCK_DIR} doesn't exist, then start working & store the ${PID_FILE}
echo $$ > ${PID_FILE}
echo "Hello world!"
rm -rf ${LOCK_DIR}
exit
else
if [ -f ${PID_FILE} ] && kill -0 $(cat ${PID_FILE}) 2>/dev/null; then
# Confirm that the process file exists & a process
# with that PID is truly running.
echo "Running [PID "$(cat ${PID_FILE})"]" >&2
exit
else
# If the process is not running, yet there is a PID file--like in the case
# of a crash or sudden reboot--then get rid of the ${LOCK_DIR}
rm -rf ${LOCK_DIR}
exit
fi
fi
A idéia é que o núcleo geral - onde eu tenho echo "Hello world!"
- é onde está o coração do seu script. O resto é basicamente um mecanismo / lógica de bloqueio baseado mkdir
. Uma boa explicação do conceito está nesta resposta :
O mkdir cria um diretório se ele ainda não existe e, se existir, define um código de saída. Mais importante, ele faz tudo isso em uma única ação atômica, tornando-o perfeito para esse cenário.
Portanto, no caso do seu rsync
processo, eu recomendaria o uso desse script apenas alterando o echo
comando para seu rsync
comando. Além disso, mude LOCK_NAME
para algo como RSYNC_PROCESS
e então você estará pronto.
Agora, com o seu rsync
envolto neste script, você pode configurar o cron para executar a cada minuto, sem qualquer risco de uma condição de corrida em que dois ou mais rsync
processos estejam lutando para fazer a mesma coisa. Isso permitirá aumentar a velocidade ou as rsync
atualizações, o que não eliminará o problema de transferência parcial de arquivos, mas ajudará a acelerar o processo geral, para que o arquivo completo possa ser copiado adequadamente em algum momento.
lsyncd
. Ele permite que você tenha “hot folders” que realmente prestem atenção à atividade nelas e, em seguida, atuem nesses arquivos quando forem feitas alterações. Eu usorsync
muito conforme descrito em minha resposta, mas usolsyncd
em casos que exigem uma forma de ação não cron / mais imediata.Sim - e o arquivo poderá estar corrompido se o rsync estiver lendo o arquivo ao mesmo tempo em que está sendo gravado.
Você pode tentar isso: /unix//a/2558
Você também pode criar um script com lsof:
Um código de saída 0 significa que o arquivo está em uso e o código de saída 1 significa que não há atividade nesse arquivo.
fonte