0

我的要求是仅在未访问文件时才替换文件。我有以下片段:

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

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

谢谢。

4

2 回答 2

1

file我的要求是仅在未访问时更换。

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

file在不干扰任何程序读/写的情况下更换file

如果是这种情况,您可以使用一种非常简洁的行为:在类 Unix 系统中,文件描述符始终指向打开它们的文件(而不是路径)。您可以移动甚至删除相应的路径。另请参阅UNIX 命令 mv 和 rm 如何处理打开的文件?.

例子:

打开终端并输入

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
于 2019-05-01T14:41:55.480 回答
0

Consider lsof.

mvWhenClear() {
  while [[ -f "$1" ]] && lsof "$1"
  do sleep $delay
  done
  mv "$1" "$2" # still allows race condition
}
于 2019-05-01T13:32:42.513 回答