Se o Apache está escrevendo um arquivo de algum tipo em um lugar e não completou a gravação e então rsync
entra em ação, rsync
copiará o que estiver lá.
Significado se o Apache está lidando com um arquivo de 5MB, apenas 2MB é gravado e rsync
entra em ação, o arquivo parcial de 2MB será copiado. Então, esse arquivo parece estar "corrompido" no servidor de destino.
Dependendo do tamanho dos arquivos que você está usando, você pode usar a opção --inplace
em rsync
para fazer o seguinte:
This option changes how rsync transfers a file when the file's data needs to be updated: instead of the default method of creating a new copy of the file and moving it into place when it is complete, rsync instead writes the updated data directly to the destination file.
O benefício disso é que, se um arquivo de 5MB tiver apenas 2MB copiado na primeira execução, a próxima execução será de 2MB e continuará a copiar o arquivo até que os 5MB completos sejam colocados.
O negativo é que poderia criar uma situação em que alguém estivesse acessando o servidor da Web enquanto um arquivo estivesse sendo copiado e, em seguida, veria 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 colocá-lo em prática imediatamente. Mas --inplace
é bom para cenários em que grandes arquivos e restrições de largura de banda podem impedir que um arquivo grande seja copiado facilmente do quadrado.
Dito isso, você afirma isso; ênfase é minha:
Every five minutes has cron run rsync…
Então, eu suponho que você tenha algum script básico para gerenciar este 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 que rsync
dê passos um para o outro, se for mais rápido. Ou seja, se você executá-lo a cada minuto, há o risco de que um ou mais dos processos rsync
continuem sendo executados devido ao tamanho do arquivo ou à velocidade da rede, e o próximo processo estaria apenas em concorrência com ele; uma condição de corrida.
Uma maneira de evitar isso é envolver todo o seu comando rsync
em um script bash que verifica um bloqueio de arquivo; abaixo é uma estrutura de script bash boilerplate eu uso para casos como este.
Note que algumas pessoas recomendam usar flock
, mas como flock
não está instalado em alguns sistemas que eu uso - e eu pulo muito entre o Ubuntu (que tem) e o Mac OS X (o que não) muito - eu use este framework simples sem qualquer 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 ideia é que o núcleo geral - onde eu tenho echo "Hello world!"
- é onde está o coração do seu roteiro. O resto é basicamente um mecanismo de travamento / lógica baseado em mkdir
. Uma boa explicação do conceito está nesta resposta :
mkdir creates a directory if it doesn't exist yet, and if it does, it sets an exit code. More importantly, it does all this in a single atomic action making it perfect for this scenario.
Portanto, no caso do seu processo rsync
, eu recomendaria usar esse script apenas alterando o comando echo
para o comando rsync
. Além disso, altere o LOCK_NAME
para algo como RSYNC_PROCESS
e, em seguida, você está pronto.
Agora, com seu rsync
agrupado neste script, você pode definir a tarefa cron para ser executada a cada minuto sem qualquer risco de uma condição de corrida em que dois ou mais processos rsync
estejam lutando para fazer a mesma coisa. Isso permitirá aumentar a velocidade ou rsync
de atualizações, o que não eliminará a transferência de arquivos parciais, mas ajudará a acelerar o processo geral para que o arquivo inteiro possa ser copiado corretamente em algum momento.