The hidden danger of using rsync to copy files instead of cp

July 31, 2018

I have a long standing reflexive habit that most of them time when I want to copy files around, I reach for 'rsync -a' by default. I do it on the command line, and I do it in things like our local postinstall system setup scripts. It's not really necessary these days ('cp -a' now works fine on everything I commonly use), but I started doing this in an era when rsync was the clearly safest choice for a 'copy file, preserving all attributes, no matter what system I'm on' command. Today I made a mistake and was reminded that this is not necessarily the best idea, because there is a small difference in behavior between rsync and cp here.

What happened today is that in a system setup script, I wrote:

set -e
[...]
rsync -a /master/loc/etc/cron.d/cron-thing /etc/crond.d/

I ran the script, it went fine, and then afterward the system didn't actually seem to be doing what the cron.d entry was supposed to have it do. I spent some time wondering if I'd gotten some other bit of the system setup wrong, so that the script I was invoking from cron couldn't do anything, and then finally I looked in /etc/cron.d for some reason and the penny dropped.

You see, the important difference between rsync and cp here is that rsync will create a destination directory if necessary and cp won't. The drawback of this sometimes-handy behavior is that rsync's behavior hides typos. Had I written 'cp -a ... /etc/crond.d/', the cp would have errored out (and then the entire script would have aborted). With rsync, it quietly created /etc/crond.d and put my cron-thing in it, just as I'd typed but not as I'd wanted.

After this happened, I went back through this script and turned all of my reflexive 'rsync -a' usage into 'cp -a'. I've been burned once, I don't need to stub my toe a second time. I don't currently plan to revise our existing (working) scripts just for this, but certainly I'm now going to try to shift my reflexes and use 'cp -a' in the future.

(In this sort of context, even if I want the directory created too I think it's better to use 'mkdir -p' in order to be explicit about it. On the command line I might exploit rsync's side effect, but in a script there's no reason to be that compact and obscure.)

Written on 31 July 2018.
« My own configuration files don't have to be dotfiles in $HOME
Ubuntu 18.04's problem with Amanda's amrecover »

Page tools: View Source, Add Comment.
Search:
Login: Password:
Atom Syndication: Recent Comments.

Last modified: Tue Jul 31 23:14:50 2018
This dinky wiki is brought to you by the Insane Hackers Guild, Python sub-branch.