保证文件夹的原子移动

时间:2012-03-23 13:12:48

标签: linux bash

我有一个脚本在XX:00每分钟运行一次。该脚本循环遍历给定目录中的所有子文件夹,并对内部文件执行操作;

folder=/path/to/directory #Starting directory
someerror=0 #Did we have an error?

#CD to directory. Does it even exist?
cd $folder
RETVAL=$?
[ $RETVAL -eq 0 ] && echo Success changing directory to $folder && mainfolderexist=1
[ $RETVAL -ne 0 ] && echo Failure changing directory to $folder && mainfolderexist=0

if [ $mainfolderexist -eq 1 ]; then
    shopt -s nullglob
    for dir in $folder/*/
    do
    thedirname=`basename $dir` #Get directory name
    #cd to sub dir. Does it even exist?
    cd $dir
    RETVAL=$?
    [ $RETVAL -eq 0 ] && echo Success changing directory to $dir && subfolderexist=1
    [ $RETVAL -ne 0 ] && echo Failure changing directory to $dir && subfolderexist=0
    if [ $subfolderexist -eq 1 ]; then
        #perform some operation on all files in this directory
        someApp -someArgs --name=$thedirname *
    else #sub folder doesn't exist
        someerror=1
        break
    fi

    #next folder
    done
else #main folder doesn't exist
    someerror=1
fi

#REPEAT (only if no errors occured)
if [ $someerror -eq 0 ]; then
at now + 1 minutes << END
/bin/bash "$0" "$@"
END
fi

我使用它的方式是使用SFTP将目录上传到服务器,到/home/incoming这样的文件夹,一旦目录完全上传,我会将其移至/path/to/directory。现在这是我担心的部分。

到目前为止,我一直在确保只在XX:XX:02和XX:XX:50之间移动目录,但这是否甚至是必要的?我想自动上传+移动过程而不考虑系统时间,所以我想知道;

  1. 如果目录正在XX:00移动(mv "somedir" "/path/to/directory/somedir")并且脚本运行,循环遍历所有目录,该怎么办?
  2. 如果系统在mv命令期间断电,该怎么办?如果目录最终会被移动一半或类似的东西,我将不得不在执行上述脚本之前编写一个验证这个的脚本。

3 个答案:

答案 0 :(得分:14)

如果源路径和目标路径位于同一文件系统上,则mv是原子操作。由于它实际上不涉及复制或以其他方式重新定位文件,因此您的目录永远不会处于“半移动”状态。

另一方面,如果您的源路径和目标路径位于不同的文件系统上,那么mv实际上是一个副本,然后删除整个树,这可能需要大量的时间,如果被打断,将使事情处于半完成状态。

答案 1 :(得分:4)

我相信mv是一个原子操作(移动目录只是重命名目录,它不会移动磁盘上的任何文件)。 mv使根据this的sys-call rename是原子的(受某些限制)。

  

如果newpath已经存在,它将被原子替换(受一些条件限制 - 请参阅下面的错误),这样就没有任何一点试图访问newpath的其他进程会发现它丢失。

答案 2 :(得分:0)

请记住,当一个(或两个)使用加密作为软件时,即使您在同一个光盘和分区中,移动也不是原子的。例如:同一台机器中的2个用户在/ home中有目录。如果其中一个使用加密的主目录,则移动将不是原子的,因为它需要在移动之前加密/解密或解密/加密或加密或解密文件