在脚本运行时更改文件会影响脚本吗?

在脚本运行时更改文件会影响脚本吗?

我有一个像这样设置的脚本:

cat file | while read line; do 
    
    # some stuff
    
done

如果我file在脚本运行时进行更改,这会影响脚本的执行吗?此外,如果我将脚本重写为:

while read line; do
    
    # some stuff
    
done < file

如果这很重要,那么更改文件可能是任何操作,从添加一两行到完全擦除文件。

答案1

是的,在这两种情况下,文件姓名仅解析一次,但文件内容在整个脚本运行时,这些文件都是以增量方式(流式)读取的。操作系统不会自动提供任何类型的隔离或版本控制。如果您更改或附加同一文件中的数据(保留其 inode 编号和所有内容),则只要读取指针到达该位置,程序就会开始通过同一文件句柄查看新数据。

但根据剧本的编写方式,一定数量在脚本开始处理数据之前,可以缓冲数据。在您的第一个脚本中,“cat”和“while”之间的管道可以容纳大量数据(据我所知为 64 kB),这意味着“cat”已经读取了比“while”循环当前正在处理的数据更多的数据。

例如,如果循环当前正在处理第 3 行,那么 'cat 的读取指针可能已经位于第 100 行,已经读取并缓冲了到此点为止的所有数据。如果脚本当前正在处理最后几行,那么 'cat' 将已经一直读取到文件末尾并停止 - 因此附加更多数据将不是不再受到关注。

在第二个示例中,没有管道,因此不会发生如此大量的缓冲。但是,“read”命令仍然会缓冲少量数据 - 它不是逐字节读取直到换行符,而是一次读取整个 4 kB 的数据。因此,当循环位于第 3 行时,它可能还读取了第 4 行甚至第 5 行的开头。

最后请注意,通过文本编辑器更改文件可能并不总是保留相同的文件对象——某些文本编辑器会重命名/删除原始文件并在该位置创建一个全新的文件。如果发生这种情况,它将不是被你的脚本注意到,因为它(第一个例子中的“cat”,第二个例子中的“bash”本身)已经有一个打开的文件句柄,并且将继续从同一个旧文件对象读取。

相关内容