bash 中有效建立锁

有时候需要防止一段代码在被同时执行,就需要使用锁来防止代码重入。常常见到这样的代码:

if [ -f /var/lock/mylock ]; then
  touch /var/lock/mylock
  ...
  rm -f /var/lock/mylock
fi

但实际上,这样是有问题的。如果两个进程在 test ( [ ) 和 touch 之间,另一个进程同时执行,就会出现竞争问题,最后就可能出现同时运行的情况。要避免这种情况出现,就得改一下加锁的方式。可以用 mkdir 代替 touch,这样在锁目录以及存在的时候,会直接出错;

if mkdir /var/lock/mylock 2>/dev/null; then
  ...
  rm -rf /var/lock/mylock
fi

或者先用 set -C ,让 > 重定向在文件已经存在时出错,然后用 echo … > 来生成锁文件

if ( set -C; echo $$> /var/lock/mylock 2>/dev/null); then
  ...
  rm -f /var/lock/mylock
fi

这两种方法可以保证加锁和检测锁是一个原子操作,避免竞争问题。

5 thoughts on “bash 中有效建立锁

  1. 11 December 26, 2011 / 7:11 pm

    rm -rf 真是个邪恶的命令,何不用 rmdir 替代一下 ^_^

    • 神仙 December 27, 2011 / 5:31 am

      恩,rmdir只能删除空目录。不过我自己是在 mkdir 以后,又往里面扔了一点运行信息。

  2. 花开 February 19, 2012 / 1:17 am

    有一个现成的工具做这个事情,lockfile,例子:

    lockfile /tmp/import.lock
    do_something
    rm -f /tmp/import.lock

    意思你懂的……

    • 花开 February 19, 2012 / 1:18 am

      RHEL上,lockfile属于procmail包。

  3. 绚丽也尘埃 March 12, 2012 / 2:14 am

    学习啦,感觉lockfile不错,不过每次要手动杀死等待的进程,要不然这些进程不会退出。

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s