Atomically swap contents of two files on Linux
You can use the (fairly recent) linux syscall renameat2
Here is the definition :
int renameat2(int olddir, const char *oldname,
int newdir, const char *newname, unsigned int flags);
You can find its source code on the kernel's Git repo if needed.
It's basically the same as renameat
, but if you pass the flag RENAME_EXCHANGE it will swap the two files instead of renaming one into the other.
The operation is atomic.
Shortest way to swap two files in bash
Add this to your .bashrc:
function swap()
{
local TMPFILE=tmp.$$
mv "$1" $TMPFILE
mv "$2" "$1"
mv $TMPFILE "$2"
}
If you want to handle potential failure of intermediate mv
operations, check Can Bal's answer.
Please note that neither this, nor other answers provide an atomic solution, because it's impossible to implement such using Linux syscalls and/or popular Linux filesystems. For Darwin kernel, check exchangedata
syscall.
How to swap filenames in Unix?
ok, stupid question, but why can't you simply do something like (in a shell script):
mv $fileA $fileA.$$
mv $fileB $fileA
mv $fileA.$$ $fileB
and yes of course it uses a temporary file, but its more concise then the other answers.
Moving a directory atomically
You can do this if you use symlinks:
Let's say alpha is a symlink to directory alpha_1, and you want to switch the symlink to point to alpha_2. Here's what that looks like before the switch:
$ ls -l
lrwxrwxrwx alpha -> alpha_1
drwxr-xr-x alpha_1
drwxr-xr-x alpha_2
To make alpha refer to alpha_2, use ln -nsf:
$ ln -nsf alpha_2 alpha
$ ls -l
lrwxrwxrwx alpha -> alpha_2
drwxr-xr-x alpha_1
drwxr-xr-x alpha_2
Now you can remove the old directory:
$ rm -rf alpha_1
Note that this is NOT actually a fully atomic operation, but it does happen very quickly since the "ln" command both unlinks and then immediately recreates the symlink. You can verify this behaviour with strace:
$ strace ln -nsf alpha_2 alpha
...
symlink("alpha_2", "alpha") = -1 EEXIST (File exists)
unlink("alpha") = 0
symlink("alpha_2", "alpha") = 0
...
You can repeat this procedure as desired: e.g. when you have a new version, alpha_3:
$ ln -nsf alpha_3 alpha
$ rm -rf alpha_2
How does one atomically replace a directory with another one in Java?
I am afraid you can't. Not at the SO level at least. So even if you manage "atomicity" in the context of your java application, you have no guarantee about some other "rogue" process interfering at the actual filesystem level.
If I were you, I'd read this article (quite old, but should give you some ideas) and then see if you can port the suggested approach to a more modern version .
Oh, wait, someone did this already!
And apparently your aren't the first one to ask here, either
Best of luck...
Is file append atomic in UNIX?
A write that's under the size of 'PIPE_BUF' is supposed to be atomic. That should be at least 512 bytes, though it could easily be larger (linux seems to have it set to 4096).
This assume that you're talking all fully POSIX-compliant components. For instance, this isn't true on NFS.
But assuming you write to a log file you opened in 'O_APPEND' mode and keep your lines (including newline) under 'PIPE_BUF' bytes long, you should be able to have multiple writers to a log file without any corruption issues. Any interrupts will arrive before or after the write, not in the middle. If you want file integrity to survive a reboot you'll also need to call fsync(2)
after every write, but that's terrible for performance.
Clarification: read the comments and Oz Solomon's answer. I'm not sure that O_APPEND
is supposed to have that PIPE_BUF
size atomicity. It's entirely possible that it's just how Linux implemented write()
, or it may be due to the underlying filesystem's block sizes.
Related Topics
Awk, Pipe and Tail -F Giving Unexpected Behavior
Cache Coloring on Slab Memory Management in Linux Kernel
Force Netcat to Send Messages Immediately (Without Buffering)
Conditional Awk Hashmap Match Lookup
Scp Command Between 2 Servers with 2 Different .Pem Keys
Ubuntu/Fedora: How to Add Applications in The Menus
Linux/Unix Socket Self-Connection
Linux: Update Embedded Resource from Executable
How to Launch Linux Subshell for Ssh_Askpass to Work in Linux
Unix Unzip: How to Batch Unzip Zip Files in a Folder and Save in Subfolders
Path Issue After Compiling Curl
Firefox Not Closing After Selenium Tests Are Run
How to Trace The Write System Call in The Linux Kernel
Linux-Based Solution for Domain Management
Ssl: Nancyfx Selfhost Mono Linux (Pi)
Svn Checkout Fails with "Chunk Delimiter Was Invalid" - What Can Be Done