将输出重定向到文件是否对文件施加锁定?


30

如果我有命令

$ ./script >> file.log

被两次调用,第二次调用在第一个调用结束之前发生,会发生什么?

第一次调用是否在输出文件上获得排他锁?如果是这样,第二个脚本在尝试编写时是否失败,或者外壳程序是否接受输出(允许脚本结束)并抛出错误?

还是日志文件被写入两次?


1
我不知道默认情况下会锁定文件的任何系统。这两个程序更有可能最终会交错写入,因为两者都将处于追加模式。结果将是不可预测的。代替“ hello world”,您可以获得“ hweolrllod”。
2012年

Answers:


18

由于您使用>>,这意味着追加,因此每个实例的输出的每一行都将按照其发生的顺序进行追加。

如果你的脚本输出打印1\n,通过5\n与每实例两者之间有一秒的延迟启动2.5秒后你会得到这样的:

1
2
1
3
2
4
3
5
4
5

因此,请回答您的问题:不。


23

Unix系统基本上避免了强制锁定。在某些情况下,内核会锁定文件以防止用户程序对其进行修改,但是如果只是由另一个程序编写则不会。没有Unix系统会锁定文件,因为程序正在写入文件。

如果您希望脚本的并发实例不会踩在彼此的脚趾上,则需要使用诸如的显式锁定机制。flock lockfile

当您打开要追加的文件时,>>可以确保每个程序始终写入文件末尾。因此,多个实例的输出将永远不会相互覆盖,并且如果轮流进行写入,则其输出将与写入顺序相同。

可能发生的不好的事情是,如果这些实例之一写入了几块输出,并希望它们一起出现。在一个实例的连续写操作之间,其他实例可以执行自己的写操作。例如,如果实例1写入foo,则实例2写入,hello而只有实例2写入bar,则文件将包含foohellobar

进程在调用write系统调用时有效地将其写入文件。调用write是原子的:每次调用都write写入一个不会被其他程序中断的字节序列。通常,一次调用write有效写入多少数据是有限制的:对于较大的大小,仅写入数据的开头,并且应用程序必须write再次调用。此外,许多程序执行缓冲:它们将数据累积在一个内存区域中,然后将这些数据写成一个块。某些程序在整行或其他有意义的分离之后刷新输出缓冲区。使用此类程序,您可以期望整行不会中断(只要它们不太长(最多几千字节;这取决于操作系统))。如果程序没有在有意义的位置刷新,而仅基于缓冲区大小,您可能会看到一个实例中的4kB,然后另一个实例中的4kB,然后又是第一个实例中的4kB,依此类推。

By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.