A while back I wrote a shell script to do a “safe” file copy on a Linux system. I use it somewhat frequently for managing servers. It basically copies a file in a completely atomic way. Programs accessing the file always see either the complete original file or the complete new file; never anything else.
Because it’s a little involved, I though it would be nice to share it publicly, so here it is.
The script is in safe-cp.sh. You copy a
file with safe-cp.sh source-file destination-file
. More details are
available by running safe-cp.sh --help
.
The program ensures three things:
-
If the destination file existed before running the program, a file always exists with that name. There is never a time when the old file has been removed but the new one has not yet been created.
-
The destination file is always complete and whole. Either the entirety of the old version of the file is available or the entirety of the new version of the file is available. There is never a time when the destination file is either empty or contains an incomplete copy of either the old or new data.
-
The contents of the original file always exist in the filesystem. After the copy, the old data exists—with the same inode—in a copy of the original file with a different name. This ensures that if a program has an open filehandle to the file, its view of the data is unchanged. The program won’t see the new data unless it closes and reopens the file, but it will never see inconsistent data.
You’d think the guarantees in the last point would be a given because of how Unix handles unlinking files with open filehandles, but I’ve seen NFS mounts that didn’t behave correctly in this regard.
Fundamentally, the script works by making sure a copy of the new file exists in the same filesystem as the destination, hard-linking the old file to a new filename, then renaming the copy of the new file to the destination name. That final rename is atomic, while the hardlinking ensures the original file and inode are preserved.
You can read through the script for the precise details, of course.