Take the 2-minute tour ×
Server Fault is a question and answer site for professional system and network administrators. It's 100% free, no registration required.

We use rsync to update a mirror of our primary file server to an off-site colocated backup server. One of the issues we currently have is that our file server has > 1TB of mostly smaller files (in the 10-100kb range), and when we're transferring this much data, we often end up with the connection being dropped several hours into the transfer. Rsync doesn't have a resume/retry feature that simply reconnects to the server to pickup where it left off -- you need to go through the file comparison process, which ends up being very length with the amount of files we have.

The solution that's recommended to get around is to split up your large rsync transfer into a series of smaller transfers. I've figured the best way to do this is by first letter of the top-level directory names, which doesn't give us a perfectly even distribution, but is good enough.

I'd like to confirm if my methodology for doing this is sane, or if there's a more simple way to accomplish the goal.

To do this, I iterate through A-Z, a-z, 0-9 to pick a one character $prefix. Initially I was thinking of just running

rsync -av --delete --delete-excluded --exclude "*.mp3" "src/$prefix*" dest/

(--exclude "*.mp3" is just an example, as we have a more lengthy exclude list for removing things like temporary files)

The problem with this is that any top-level directories in dest/ that are no longer present present on src will not get picked up by --delete. To get around this, I'm instead trying the following:

rsync \
--filter 'S /$prefix*' \
--filter 'R /$prefix*' \
--filter 'H /*' \
--filter 'P /*' \
-av --delete --delete-excluded --exclude "*.mp3" src/ dest/

I'm using the show and hide over include and exclude, because otherwise the --delete-excluded will delete anything that doesn't match $prefix.

Is this the most effective way of splitting the rsync into smaller chunks? Is there a more effective tool, or a flag that I've missed, that might make this more simple?

share|improve this question

3 Answers 3

up vote 3 down vote accepted

My solution to this was a different two-pass approach, where I trade off some disk space. I do rsync --only-write-batch on the server, then rsync the batch file itself to the destination, looping until the rsync succeeds. Once the batch is fully over rsync --read-batch on the destination recreates all the changes.

There are some unintended benefits to this for me as well:

  • because I'm more concerned that the backup "exists" than is "usable" I don't actually do the read-batch on the receiving end every day -- most of the time the batch is relatively small

  • I've been experimenting with --checksum-seed=1 ... I might be mis-reading the documentation but I think it makes the batch files more syncable (ie. when I don't do the --read-batch any given day, the next day's batch syncs faster because the previous day's batch is a good basis)

  • if the batch gets too big to send "in time" over the internet, I can sneaker-net it over on an external drive. By in-time I mean that if I can't get the batch over and read before the next day's backup starts.

  • although I don't personally do this, I could have two offsite backups in separate locations and send the batch to both of them.

share|improve this answer

Not exactly answering your question, but another option I use pretty often is doing this in a two pass approach: first build a list of files, then split the list of files to be transferred and feed the file list into rsync/cpio/cp etc.

rsync --itemize-changes <rest of options> will print out a list of files to be transferred with a bunch of useful metadata, from that output it's fairly easy to extract the filenames and then do the actual copy with either rsync --files-from or another tool.

Could be useful for your situation - resuming from a broken transfer would be much quicker.

share|improve this answer

I would suggest you to keep a look into the connection problem, instead of trying to solve it by creating another "problem".

It's not a common behavior. Are you using rsync through SSH or rsyncd?

As far as I know most "closed" connections occur when there is no data being transferred between endpoints.

share|improve this answer
    
It's running via ssh as we're without a VPN end-point at the coloc. We've experimented using stunnel, but it another layer that has introduced another layer of connection reset bugs. As for the connection dropping, it isn't a problem that happens immediately -- we usually experience drops like this around the 24-48 hour mark. Diagnosing a dropped connection like this is difficult, especially when there is likely little you can do to fix it. I think it's more pragmatic to plan for the inevitable network failure with a solution like this that significantly reduces overhead in reconnecting. –  Gabe Martin-Dempesy Aug 11 '10 at 20:31
    
Have you tryed the KeepAlive setting in sshd.conf? Another idea is to try the fuse-sshfs with "-o reconnect" in the "mount" options. And use it for rsync is a local mount point. –  HGF Aug 11 '10 at 22:27
    
be careful using rsync with local-to-local as it may end up doing whole-file copy. –  Andrew Aug 12 '10 at 0:18

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.