【问题标题】:Using flock to read and write to a file in bash使用flock在bash中读取和写入文件
【发布时间】:2015-11-18 20:36:04
【问题描述】:

我有一个可以并行运行多次的 bash 脚本,我需要能够检查文件中的值并对其进行修改。理想情况下,我希望首先到达那里的任何脚本实例都能够在不受另一个实例干扰的情况下进行读取和写入。我想我可以用flock来做到这一点,但似乎有些命令被忽略了——我猜是因为他们无法获得锁?

这是我目前所拥有的:

myfunc () {
    { flock -x 3 ; count=$(cat <&3); } 3< countfile
    { flock -x 3 ; echo $((count+1)) >&3; } 3> countfile
}

这是从子 shell 运行的,所以我必须通过文件进行计数。

所以,有两件事

  1. 这不是使用同一个锁来读写——我想要,但我不知道怎么做
  2. 为什么有时会忽略我的读取?

谢谢!

【问题讨论】:

  • 你可能可以用flock 做你想做的事,假设所有进程都同意这样做(因为flock 只提供自主 锁定)。但是,尚不清楚您的问题实际上是如何表现出来的。如果您提供一个最小的、完整的示例,我们可以重现您的问题,您将获得更好的帮助。
  • 您现有的代码会锁定文件、读取文件、解锁文件、再次锁定文件、写入文件和解锁文件。这显然是不安全的,因为这意味着文件可能在第一个锁被释放和第二个锁发生之间被其他人更改

标签: bash parallel-processing flock


【解决方案1】:

您不需要为读取和写入进程重复使用相同的描述符。在其他语言中,这将是一种代码异味,但 bash 不支持在现有 FD 中进行搜索,不幸的是,这是必要的问题。

myfunc () {
  {
    flock -x 3 || return
    count=$(<countfile)
    echo "$((count + 1 ))" >countfile
  } 3<>countfile
}

也就是说 - 并非所有解决方案都是原生的! @telotortium has written an excellent C helper 可用于在预先打开的 FD 中查找;如果您要使用他们的代码回溯到文件的开头(或类似于将其截断为 0 并将 FD 移到那里),您可以重用单个文件描述符进行读取和写入。

【讨论】:

    【解决方案2】:

    我遵循了here 的示例。我不完全确定为什么切换到使用可变流描述符会有所帮助,但我完成了我所需要的。另一件不同的事情是,在示例中,他们使用的是子shell 中的实际文件名,它被锁定,而不是实际引用流。

    这对我来说是新事物,所以我欢迎 cmets。

    【讨论】:

    • 你能确切地展示一下你是如何遵循这个例子的吗?它如何解决您的问题并不完全清楚,因此新代码是否与问题中给出的问题相同(重新:单独的锁而不是连续的互斥锁)。
    猜你喜欢
    • 2015-03-29
    • 2015-07-26
    • 1970-01-01
    • 1970-01-01
    • 2019-01-24
    • 2010-11-11
    • 1970-01-01
    • 2020-04-16
    • 2015-09-29
    相关资源
    最近更新 更多