读写两个进程的同一个文件是不是需要lockfile

Posted

技术标签:

【中文标题】读写两个进程的同一个文件是不是需要lockfile【英文标题】:Is lockfile necessary for reading and writing the same file of two processes读写两个进程的同一个文件是否需要lockfile 【发布时间】:2019-01-17 13:31:47 【问题描述】:

我正在使用 Bash 脚本并遇到这种情况:

一个 bash 脚本会将内容写入文件,而另一个 bash 脚本将从同一个文件中读取内容。

在这种情况下,是否需要lockfile?我想我不需要使用lockfile,因为只有一个读取过程和一个写入过程,但我不确定。

Bash write.sh:

#!/bin/bash

echo 'success' > tmp.log

Bash read.sh:

#!/bin/bash
while :
do
    line=$(head -n 1 ./tmp.log)
    if [[ "$line" == "success" ]]; then
        echo 'done'
        break
    else
        sleep 3
    fi
done

顺便说一句,write.sh 可以写几个关键词,例如successfail 等。

【问题讨论】:

如果你只想要文件的第一行,只需使用read line < ./tmp.log 【参考方案1】:

虽然许多程序员忽略了这一点,但您可能会遇到问题,因为写入文件不是原子的。当作者这样做时

echo success > tmp.log

它可以分成两个(或更多)部分:首先它写入suc,然后它写入cess\n

如果阅读器在这些步骤之间执行,它可能只得到suc 而不是整个success 行。使用锁定文件可以防止这种竞争条件。

shell echo 命令的短写入不太可能发生这种情况,这就是大多数程序员不担心它的原因。但是,如果编写器是使用缓冲输出的 C 程序,则可以在任意时间刷新缓冲区,这可能会以部分行结束。

此外,由于阅读器每次都是从头开始读取文件,因此您不必担心从前一个中断的位置开始读取。

另一种方法是让写入器写入具有不同名称的文件,然后将文件重命名为读取器正在查找的文件。重命名是原子性的,因此您可以保证阅读全部内容或什么也不阅读。

【讨论】:

如果是这样,我认为lockfile是没有必要的,因为read.sh只有sleep 3才会读取suc。后面的循环可以得到success 你还关心文件的内容吗?看起来检查write.sh 是否简单地创建 一个名为./tmp.log 的空文件就足够了。 @chepner 我确实关心文件的内容。如您所见,read.sh 正在寻找关键字“成功”。 但是你展示的write.sh永远不会写任何东西除了 success。如果这是真的,那么使用文件的存在而不是内容作为成功的指示会更简单。 @Yves 如果其中一个可能的输出是另一个的扩展,您可能会遇到问题。如果作者可以写successful partially,那么如果你的读者在作者写完之前读到了,那么你的读者可能会误会。【参考方案2】:

至少从您的示例来看,read.sh 看起来并不真正关心 什么 被写入 tmp.log,只是 write.sh 创建了该文件。在这种情况下,所有read.sh 需要检查的是文件是否存在。

write.sh 可以很简单

: > tmp.log

read.sh 变为

until [ -e tmp.log ]; do
  sleep 3
done
echo "done"

【讨论】:

嗯,success 只是一个例子,它可能是success,'fail` 等。这就是为什么我关心我是否应该在读写时锁定文件。 如果它不写success,你的脚本会退出吗?或者作者会在下一次尝试时覆盖第一行吗? 这听起来像是脚本在完成所有它应该做的事情时写的东西,以表明它是成功还是失败。读者只是定期检查它是否完成以及状态是什么。希望这些检查比它监控的应用程序更频繁。

以上是关于读写两个进程的同一个文件是不是需要lockfile的主要内容,如果未能解决你的问题,请参考以下文章

linux 共享内存 可不可以不加锁呢? 系统有两个进程,一个负责写入,一个负责读取

如何在 Linux 中存储 lockfile 命令的 PID

群():在没有竞争条件的情况下删除锁定的文件?

强制读写进程的内存

使用windows c++ LockFIle() 锁定文件然后从中获取流?

用于多进程读写的Java文件锁[重复]