您的位置:首页 > 其它

第一章:The Missing Code Library--10.锁定文件

2012-12-11 18:10 393 查看
任何脚本,在对共享数据文件,比如日志文件,进行读或追加写操作时,都需要一个可信赖的方法来确保别的脚本进程不会同时更新它。解决问题的思路就是使用一个独立的锁文件,就好像信号一样。它的存在表明了有一个不同的文件正在使用该数据文件,所以此时该数据文件不能被其它人使用。请求文件会等待,然后继续尝试请求使用该数据文件,希望数据文件会被快速释放掉,而判断的关键标志就在于锁文件是否被移除了。但是锁文件的运行很复杂,许多看起来万无一失的情况都有可能失败。比如下面的例子就是一个解决这个问题的典型方法:

while [ -f $lockfile ]; do
sleep 1
done
touch $lockfile


看起来像是能运行,事实上是吗?while循环会一直运行到锁文件不存在为止,然后再建立锁文件,这样是为了确保你拥有锁文件,因此你就能安全的修改文件了。如果另外一个脚本有着同样的循环来查看你的锁,它会一直尝试直到锁文件消失。可事实上,它并不会这样运行。因为在轮到别的进程时,脚本看起来就像是还没有被换出一样的在运行,可事实上并不如此。想象一下会发生什么,就是在while循环结束之后,操作touch之前,这个脚本被换出,然后被放到处理器队列中,此时,另外一个脚本就替代它运行了起来。这个另外的脚本会忠实的测试有没有锁文件,发现没有,然后创建属于自己的版本。然后在队列中的那个原来的脚本又被换进来,然后做一个touch的操作,结果就是2个脚本都认为它们进行了互斥存取,这点非常糟糕。(其实就是竟态条件)幸运的是,Stephen van den Berg和Philip Guenther(邮件过滤程序procEmail的作者),在程序中包括了一个lockfile命令,该命令允许你安全可信赖的在脚本中使用锁文件。很多Unix版本,包括Linux和Mac OS X,都有lockfile。你可以在你自己的系统上通过键入man 1 lockfile来测试是否有该命令。如果你看到了手册页,恭喜!如果没有,请从http://www.procmail.org/ 下载procEmail包,然后将lockfile命令导入你的系统。这节的脚本假定你已经有了lockfile命令,而且后面的脚本(特别是第7章,"Web and Internet Users")都会要求第10个脚本中的可信赖的锁机制。

代码:

#!/bin/sh

# filelock.sh -- 一个灵活的文件锁机制

retries="10"             # 默认的尝试次数
action="lock"             # 默认动作
nullcmd="/bin/true"     # 没有lockfile命令

while getopts "lur:" opt; do
case $opt in
l)action="lock"     ;;
u)action="unlock"   ;;
r)retries="$OPTARG" ;;
esac
done
shift $(($OPTIND - 1))

if [ $# -eq 0 ]; then
cat << EOF >&2
Usage: $0 [-l|-u] [-r retries] lockfilename
Where -l requests a lock(the default), -u requests an unlock, -r X
specifies a maximum number of retries before it fails (default = $retries)
EOF
exit 1
fi

# 确定是否有lockf或时lockfile系统应用

if [ -z "$(which lockfile | grep -v '^no')" ]; then
echo "$0 failed: 'lockfile' utility not found in PATH." >&2
exit 1
fi

if [ "$action" = "lock" ]; then
if ! lockfile -1 -r $retries "$1" 2> /dev/null; then
echo "$0: Failed: Couldn't create lockfile in time" >&2
exit 1
fi
else    # action = unlock
if [ ! -f "$1" ]; then
echo "$0: Warning: lockfile $1 doesn't exist to unlock" >&2
exit 1
fi
rm -f "$1"
fi

exit 0


运行脚本:
这个lockfile脚本并不是一个独立运行的脚本,你可以在2个终端窗口中进行测试。建立一个锁,给出一个你要锁的文件的名字,要删除锁的话,用-u选项。

运行结果:

./filelock.sh exclusive.lck
ls -al exclusive.lck
-r--r--r--  1 epost dba 1 11月 14 11:52 exclusive.lck

./filelock.sh exclusive.lck
./filelock.sh: Failed: Couldn't create lockfile in time

./filelock.sh -u exclusive.lck
ls -al exclusive.lck
ls: exclusive.lck: 没有那个文件或目录


分析脚本:
这个脚本是依靠一个锁文件的存在来证明是有锁的,如果加上一个参数的话,会更好。就是一个锁有效的最长时间。

这个脚本对老七而言,实际意义并不大,工作中几乎用不到。自己也仅做了简单的了解。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: