30 shell bash io-redirection lock
如果我有命令
$ ./script >> file.log
Run Code Online (Sandbox Code Playgroud)
被调用两次,第二次调用发生在第一个结束之前,会发生什么?
第一次调用是否获得了输出文件的排他锁?如果是这样,第二个脚本是否在尝试写入时失败,或者 shell 是否接受输出(允许脚本结束)并抛出错误?
或者日志文件被写入两次?
Gil*_*il' 23
Unix 系统基本上避免强制锁。在少数情况下,内核会锁定文件以防止用户程序修改,但如果它只是由另一个程序编写,则不会。没有 unix 系统会因为程序正在写入文件而锁定文件。
如果您希望脚本的并发实例不会相互影响,则需要使用显式锁定机制,例如.flock
lockfile
当你打开一个文件进行追加时,>>
每个程序都保证总是写入文件的末尾。所以多个实例的输出永远不会相互覆盖,如果它们轮流写入,它们的输出将与写入的顺序相同。
可能发生的坏事是,如果其中一个实例写入多个输出块并期望它们一起出现。在一个实例连续写入之间,其他实例可以执行自己的写入。例如,如果实例 1 写入foo
,然后实例 2 写入hello
,然后实例 2 写入bar
,则文件将包含foohellobar
.
进程在调用write
系统调用时有效地写入文件。对 的调用write
是原子的:每次调用都会write
写入一个不会被其他程序中断的字节序列。单个调用write
将有效写入的数据量通常是有限制的:对于较大的数据,仅写入数据的开头,应用程序必须write
再次调用。此外,许多程序执行缓冲: 他们在一个内存区域中积累数据,然后将这些数据写成一个块。某些程序在完成一行或其他有意义的分隔后刷新输出缓冲区。使用此类程序,您可以期望整行不会中断,只要它们不太长(最多几千字节;这取决于操作系统)。如果程序没有在有意义的位置刷新,而只是基于缓冲区大小,您可能会看到一个实例为 4kB,另一个实例为 4kB,然后第一个实例为 4kB,依此类推。
bah*_*mat 17
由于您使用的是>>
,这意味着附加,因此每个实例的每一行输出都将按照其出现的顺序进行附加。
如果您的脚本输出在每个输出之间有 1 秒的延迟打印1\n
出来5\n
,并且实例 2 在 2.5 秒后启动,您将得到以下信息:
1
2
1
3
2
4
3
5
4
5
Run Code Online (Sandbox Code Playgroud)
所以回答你的问题:不。