Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to Safely and Transactionally Replace a File on Linux?

The most naive, worst way I can think of to replace the contents of a file is:

f = open('file.txt', 'w')
f.write('stuff')
f.close()

Obviously, if that operation fails at some point before closing, you lose the contents of the original file while not necessarily finishing the new content.

So, what is the completely proper way to do this (if there is one). I imagine it's something like:

f = open('file.txt.tmp', 'w')
f.write('stuff')
f.close()
move('file.txt.tmp', 'file.txt') # dangerous line?

But is that completely atomic and safe? What are the proper commands to actually perform the move. If I have another process with an open connection to file.txt I assume that it will hold on to its pointer to the original file until is closes. What if another process tries to open up file.txt in the middle of the move?

I don't really care what version of the file my processes get as long as they get a complete, uncorrupted version.

like image 686
dave mankoff Avatar asked Nov 01 '12 22:11

dave mankoff


1 Answers

Your implementation of move should use the rename function, which is atomic. Processes opening the file will see either the old or the new contents, there is no middle state. If a process already has opened the file it will keep having access to the old version after move.

like image 107
Joni Avatar answered Sep 21 '22 09:09

Joni