Shell Atomic Command

风行水上 @ 2014-02-28 19:08:59
标签:

    关于Atomic可以参考 Atomic Operation and Atomic Command

    Shell Atomic Command

    • lockfile
    • flock
    • mkdir
    • ln -s

    需要注意的是,有些命令对于NFS(Network File System),是无效的。根据StackOverflow上的一个说法

    • NFSv2支持两个atomic operation: symlinkrename
    • NFSv3另外支持:create
    • NFSv2和NFSv3都不支持 mkdir

    因此,利用文件进行lock/unlock可以如下操作:

    # lock
    while ! ln -s ${f} ${f}.lock; do :; done
    
    # unlock
    mv ${f}.lock ${f}.unlock && rm ${f}.unlock
    

    Single Running Instance of Script

    有时需要一个程序只有一个正在运行的实例。

    来自StackOverflow上的一个方法:

    LOCKFILE=/tmp/lock.txt
    if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then
        # TODO: what if another instance just start here
        echo "already running"
        exit
    fi
    
    # make sure the lockfile is removed when we exit and then claim it
    trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT
    echo $$ > ${LOCKFILE}
    
    # do stuff
    sleep 1000
    
    rm -f ${LOCKFILE}
    

    其中的trap语句用于"unlock"操作——清除lock文件。

    这个方法的缺点是:如果另外一个进程恰好在检查之后启动。(代码中标记"TODO"的地方。虽然这是小概率事件)

    潜在的问题的主要原因是检查文件存在和创建文件之间有时间间隔,不是一个atomic操作。

    为了解决这个问题,可以借助mkdir命令。需要注意的是这个命令对于NFS可能是无效的。

    Is a Shell Script Atomic?

    一段Shell程序产生的代码是否是atomic呢?

    比如下面的代码借助Bash的noclobber来实现lock检测。

    set -C
    lockfile="/tmp/locktest.lock"
    if echo "$$" > "$lockfile"; then
        echo "Successfully acquired lock"
        # do work
        rm "$lockfile"    # XXX or via trap - see below
    else
        echo "Cannot acquire lock - already locked by $(cat "$lockfile")"
    fi
    

    可以借助strace命令来测试:

    $ strace -e trace=creat,open -f /bin/bash testlock 2>&1 | grep -F test.lock
    open("/tmp/testopen.lock", O_WRONLY|O_CREAT|O_EXCL|O_LARGEFILE, 0666) = 3
    

    下面是一个更为简化的用法示例:

    if (set -C; >$lockfile); then ...
    

    网络资源

    标签:

      分享到:
      comments powered by Disqus

      24/27ms