![两个脚本写入同一个文件时未出现竞争条件](https://linux22.com/image/219022/%E4%B8%A4%E4%B8%AA%E8%84%9A%E6%9C%AC%E5%86%99%E5%85%A5%E5%90%8C%E4%B8%80%E4%B8%AA%E6%96%87%E4%BB%B6%E6%97%B6%E6%9C%AA%E5%87%BA%E7%8E%B0%E7%AB%9E%E4%BA%89%E6%9D%A1%E4%BB%B6.png)
我有两个并行运行的脚本,它们回显到同一个文件。一个脚本正在回显+++++++++++++++
该文件,而另一个脚本正在回显===========
该文件。
下面是第一个脚本
#!/bin/bash
while [ 1==1 ];
do
echo "+++++++++++++++" >> log.txt
# commands
done
下面是第二个脚本
#!/bin/bash
while [ 1==1 ];
do
echo "===========" >> log.txt
# commands
done
log.txt 文件打印了大约 1400000 行,并且没有一行有像 ++== 之类的混乱大小写?
Linux 是否可以防止这种混乱的发生?如果可以,那么如何以及为什么?
答案1
简单地说,该echo
命令触发一个write
原子系统调用。
请注意,这write
并不保证写入给定的所有字节,但在这种情况下(很少数据),它会写入。
那么理论上write(fd, buffer, n)
可以写入少于n
字节并返回实际写入的写入字节数,以使程序能够写入字节buffer+n
。
管道可能会发生这种情况,因为管道不具有无限的容量。
从write(2)
如果文件是使用 O_APPEND 打开(2)的,则在写入之前首先将文件偏移量设置为文件末尾。文件偏移量的调整和写入操作作为原子步骤执行。
根据 POSIX.1,如果 count 大于 SSIZE_MAX,则结果是实现定义的;有关 Linux 上的上限,请参阅注释。
答案2
你可以尝试一下这个限制:
#!/bin/bash
outer() {
rm log.txt
inner() {
a=$(perl -e 'print "'$1'"x'$2'')
while [ 1==1 ];
do
echo $a >> log.txt
# commands
done
}
export -f inner
timeout 5 bash -c "inner '-' $1" &
timeout 5 bash -c "inner '+' $1" &
wait
sort -u log.txt
}
replace_repeats() {
# Replace
# ---
# with
# -3
perl -pe 's/((.)\2+)/"$2".length$1/e'
}
# This is OK
outer 10 | replace_repeats
outer 100 | replace_repeats
outer 1000 | replace_repeats
outer 4095 | replace_repeats
# This breaks.
# It should give:
# +4096
# -4096
outer 4096 | replace_repeats