通过">"重定向日志,每次写入日志时会不会先把已有日志读入内存,然后再追加?

疑问

1. 假设有程序不断地输出日志到 /var/log/example.log

# ./test.sh > /var/log/example.log

2. 假设这个程序会运行一年,日志量可能到达5GB.

3. 程序在每次写入新日志的时候,“>”会不会先将 /var/log/example.log 的已有数据读入内存,再追加新的日子? 如果是这样,内存会被大量占用而影响系统性能。

回答

通过 ">" 或 ">>" 输出的日志,不会先读取已有日志到内存中再追加数据,而是直接写入/追加数据。所以不用担心因为已有日志文件过大而导致内存占用。

如果每次追加数据都先读入内存再追加,不仅会导致内存占用高,IO消耗的会非常大,系统不会这么傻。

比如,我们有一个程序一直输出日志到标准输出,而我们把标准输出重定向到了文件。

# /tmp/test.sh > /tmp/output1

每次写入数据,它会往标准输出(FD=1)写入相应数据。从 strace 中可以看到如下条目:

25780 14:36:11.920608 write(1, "Wed Jun 13 14:36:11 HKT 2018\n", 29) = 29 <0.000013>

系统在处理 write() 时,会先找到当前文件(FD=1)对应的 offset,然后从 offset 开始写入数据,并相应地增加 offset.

我们可以通过以下方法来看到FD当前的 offset,它会随着日志的写入而增大:

# cat /proc/25971/fdinfo/1
pos:    1305  <---
flags:  0100001
mnt_id: 59

因此,write()不需要读入原有数据即可在恰当位置写入新数据。

可以查阅 write/lseek 的 man 手册了解更多。