【问题标题】:Replace file only if not being accessed in bash仅当不在 bash 中访问时才替换文件
【发布时间】:2019-09-20 00:18:16
【问题描述】:

我的要求是仅在不被访问时替换文件。我有以下 sn-p:

if [ -f file ]
then
    while true
    do
       if [ -n "$(fuser "file")" ]
       then
           echo "file is in use..."
       else
           echo "file is free..."
           break
       fi
   done
fi

{
   flock -x 3
   mv newfile file
} 3>file

但我怀疑我没有正确处理并发。请提供一些见解和实现这一目标的可能方法。

谢谢。

【问题讨论】:

    标签: bash unix concurrency flock fuser


    【解决方案1】:

    考虑lsof

    mvWhenClear() {
      while [[ -f "$1" ]] && lsof "$1"
      do sleep $delay
      done
      mv "$1" "$2" # still allows race condition
    }
    

    【讨论】:

      【解决方案2】:

      我的要求是仅在不被访问时替换file

      获得正确的需求可能很困难。如果您的实际要求如下,您可以将整个脚本归结为一个命令。 我对实际要求的猜测(不像原来那么严格):

      替换file而不干扰任何程序读/写file

      如果是这种情况,您可以使用一种非常简洁的行为:在类 Unix 系统中,文件描述符始终指向打开它们的文件(而不是路径)。您可以移动甚至删除相应的路径。另见How do the UNIX commands mv and rm work with open files?

      示例:

      打开终端进入

      i=1; while true; do echo $((i++)); sleep 1; done > file &
      tail -f file
      

      第一个命令将输出写入file 并在后台运行。第二个命令读取文件并继续打印其变化的内容。

      打开另一个终端并移动或删除file,例如

      mv file file2
      echo overwritten > otherFile
      mv otherFile file2
      rm file2
      echo overwritten > file
      echo overwritten > file2
      

      在执行这些命令时,请查看第一个终端中tail -f 的输出——它不会受到任何这些命令的影响。你永远不会看到overwritten

      新需求解决方案:

      由于这种行为,您可以用一个 mv 命令替换整个脚本:

      mv newfile file
      

      【讨论】:

        猜你喜欢
        • 2012-08-11
        • 2012-10-05
        • 2014-09-13
        • 1970-01-01
        • 2014-10-23
        • 2014-05-12
        • 1970-01-01
        • 2021-01-22
        • 2016-12-19
        相关资源
        最近更新 更多