2012-11-01 51 views
4

最天真,最糟糕的我能想到的方式替換文件的內容是:如何安全地和事務性地替換Linux上的文件?

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

很顯然,如果該操作在交易結束前某些時候失敗了,你失去了原有文件的內容,而不是必須完成新的內容。

那麼,什麼是完全正確的方法來做到這一點(如果有的話)。我想像是這樣的:

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

但是,這是完全原子和安全?什麼是真正執行移動的正確命令。如果我有與file.txt打開連接的另一個進程,我認爲它將保持其指向原始文件的指針,直到關閉。如果另一個流程試圖在移動中間打開file.txt會怎麼樣?

我真的不在乎我的進程得到的文件的版本是什麼,只要他們得到一個完整的,無損的版本。

回答

4

move的實現應該使用原子的rename函數。打開文件的進程將看到舊的或新的內容,沒有中間狀態。如果某個進程已經打開該文件,它將繼續訪問move之後的舊版本。

+0

我假設重命名是一個系統調用,可用於我。在移動文件之前,我需要在文件上執行任何類似於「fsync」的操作嗎? –

+1

您只需要調用重命名,請參閱「man 2 rename」。如果你不使用C,你的語言的重命名()或移動()的等價物應該起作用。請記住,臨時文件必須位於相同的文件系統上才能重命名... – Joni