The hidden danger of using
rsync to copy files instead of
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
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
some reason and the penny dropped.
You see, the important difference between
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 ...
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.)