两个脚本写入同一个文件时未出现竞争条件

两个脚本写入同一个文件时未出现竞争条件

我有两个并行运行的脚本,它们回显到同一个文件。一个脚本正在回显+++++++++++++++该文件,而另一个脚本正在回显===========该文件。

下面是第一个脚本

#!/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

相关内容