Concurrent writing to a log file from many processes
When a file is opened in append mode, the OS guarantees that all writes take place at the end. So the data from one writer will not overwrite the data from another writer.
This only applies if the file is opened in append mode, i.e. with >>
in the shell. If the creator of the file opens it with >
then that guarantee won't apply and it's possible to have this sequence:
- Process 1:
>out
; now at position 0 - Process 2:
>>out
; now at position 0 - Process 1: write
hello
, now at position 6 - Process 2: write
world
, this is written at position 6 and process 2 is now at position 12 - Process 1: write
oops
, this is written at position 6 because process 1's file position has not changed.
On Debian (since 2001 or thereabouts), the file .xsession-errors
is created by `/etc/X11/Xsession and it is opened in append mode, so everything is fine:
exec >>"$ERRFILE" 2>&1
I don't know if that's the case on all distributions that log to ~/.xsession-errors
.
As long as everybody opens the file in append mode, all output will be present. The output may be fragmented however. In practice, small enough writes to a regular file are atomic. Anything less than 512B should be small enough everywhere, and I think Linux guarantees more than that¹. So each log line should appear intact, even with multiple concurrent writers, assuming that the writers use line-buffered output and that the lines are not overly long.
¹ Note that POSIX does not guarantee anything except for pipes.
Using >>
in a POSIX shell guarantees that the file will be opened with O_APPEND
.
The Open Group Base Specifications Issue 7 states:
If the
O_APPEND
flag of the file status flags is set, the file offset shall be set to the end of the file prior to each write and no intervening file modification operation shall occur between changing the file offset and the write operation.
POSIX defines the mimimum number of bytes that can be requested to be written in a single write(2)
call (SSIZE_MAX
= 32,767). The return value is the number of bytes actually written (guaranteed atomic).
However
Not all filesystems comply. Appending to a File from Multiple Processes says:
The caveat is that not all filesystems are POSIX-compatible. Two famous examples are NFS and the Hadoop Distributed File System (HDFS). On these networked filesystems, appends are simulated and subject to race conditions.
Not everyone plays nice
While you might open using O_APPEND
, the other processes writing to the file may not. You can check for any given file:
lsof +fg <file>
Worryingly, when I run lsof +fg ~/.xsession-errors
, I see no AP
(append) flag, suggesting that the 22 processes in my listing (Manjaro Linux based on Arch) are not opening the file safely.
Only when I run cat >> ~/.xsession-errors
in another shell does the final output line include the AP
flag:
cat 3099 ravi 1w REG W,AP,LG 0,48 963 1926479 .xsession-errors
If anyone knows where this issue should be raised upstream, please comment.
Practically
If all processes open the file locally with either:
open(2)
and flagO_APPEND
fopen(3)
and the"a"
flag- POSIX
sh
>>
orbash
&>>
Then no data should be overwritten via race conditions.
Thanks to @Gilles answer for pointing me in the right direction.