Suppose I read (cat) a file while another process is rewriting its contents. Is the output predictable? What would happen?
- 3The behavior is undefined, you should never do this.daisy– daisy2012-06-26 13:40:52 +00:00Commented Jun 26, 2012 at 13:40
- See this as well: How to make reading and writing the same file in the same pipeline always “fail”?.codeforester– codeforester2019-04-04 19:21:10 +00:00Commented Apr 4, 2019 at 19:21
3 Answers
That depends on what the writer does.
If the writer overwrites the existing file, then the reader will see the new content when the writer overtakes the reader, if ever. If the writer and the reader proceed at variable speeds, the reader may alternatively see old and new content.
If the writer truncates the file before it starts to write, the reader will run against the end of the file at that point.
If the writer creates a new file then moves the new file to the old name, the reader will keep reading from the old file. If an opened file is moved or removed, the processes that have the file opened keep reading from that same file. If the file is removed, it actually remains on the disk (but with no way to open it again) until the last process has closed it.
Unix systems tend not to have mandatory locks. If an application wants to ensure that its writer component and its reader component don't step on each other's toes, it's up to the developer to use proper locking. There are a few exceptions where a file that's open by the kernel may be protected from writing by user applications, for example a loop-mounted filesystem image or an executable that's being executed on some unix variants.
- Gilles, does your explanation also apply in
ftp/sftpscenarios? Say a process starts reading a transmittedftpfile while another version of the same file is overwriting it due to a new transmission.iruvar– iruvar2014-08-04 20:27:28 +00:00Commented Aug 4, 2014 at 20:27 - @1_CR Yes. In that case, the writer and the reader are the ftpd processes.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2014-08-04 21:46:24 +00:00Commented Aug 4, 2014 at 21:46
- what's the meaning of overtake here?Victor Choy– Victor Choy2016-10-10 07:02:53 +00:00Commented Oct 10, 2016 at 7:02
- @VictorChoy Standard meaning: to start behind/after someone else and at some point move ahead of them.Gilles 'SO- stop being evil'– Gilles 'SO- stop being evil'2016-10-10 17:50:52 +00:00Commented Oct 10, 2016 at 17:50
It's a classic race condition, so the outcome is unpredictable by definition.
Among others, it depends on
fopen(3)oropen(2)write modes,- how/if the writer is buffering its output,
- how the reader is reading the file,
- the speed difference between the reader and writer,
- the time difference between the read and writer's start.
- And of course, on modern multi-core machines, things are complicated even more by other factors lower down (e.g. process scheduling).
If you need to be able to read a file while it's being rewritten, then you can make the writer make a transient copy of the file, modify that, then copy it back to the original file. This the way rsync does this, for instance. There are a number of ways to implement this, but no free lunch. Each method has its own shortcomings and repercussions.
- 1This answer is far more comprehensive than mine. Deleting my answer.killermist– killermist2012-06-26 14:22:48 +00:00Commented Jun 26, 2012 at 14:22
Previous responders have more comprehensive explanations than this, but here's a trick that definitely works as well, pretty much doing exactly what he wants:
$ tail -f <filename> Will show you the end of the file as it's being written. Handy if you want to pipe STDERR to a file but still see it in another terminal window, for example.