将输出重定向到文件是否会对该文件应用锁定?

将输出重定向到文件是否会对该文件应用锁定?

如果我有一个命令

$ ./script >> file.log

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

第一次调用是否获得输出文件的独占锁?如果是这样,第二个脚本在尝试写入时是否会失败,或者 shell 是否接受输出(允许脚本结束)并抛出错误?

或者日志文件是否被写入两次?

答案1

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

如果您希望脚本的并发实例不互相打扰,则需要使用显式锁定机制,例如flock lockfile

当您打开文件进行追加时(确实>>如此),每个程序都保证始终写入文件的末尾。因此,多个实例的输出永远不会互相覆盖,如果它们轮流写入,它们的输出将与写入的顺序相同。

可能发生的坏事是,如果其中一个实例写入了多个输出块并期望它们一起输出。在一个实例的连续写入之间,其他实例可以执行自己的写入。例如,如果实例 1 写入foo,然后实例 2 写入hello,然后只有实例 2 写入bar,则该文件将包含foohellobar.

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

答案2

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

如果您的脚本输出打印1\n完毕5\n,每个输出之间有 1 秒的延迟,并且实例 2 在 2.5 秒后启动,您将得到以下结果:

1
2
1
3
2
4
3
5
4
5

所以回答你的问题:不。

相关内容