第一章:The Missing Code Library--10.锁定文件
2012-12-11 18:10
393 查看
任何脚本,在对共享数据文件,比如日志文件,进行读或追加写操作时,都需要一个可信赖的方法来确保别的脚本进程不会同时更新它。解决问题的思路就是使用一个独立的锁文件,就好像信号一样。它的存在表明了有一个不同的文件正在使用该数据文件,所以此时该数据文件不能被其它人使用。请求文件会等待,然后继续尝试请求使用该数据文件,希望数据文件会被快速释放掉,而判断的关键标志就在于锁文件是否被移除了。但是锁文件的运行很复杂,许多看起来万无一失的情况都有可能失败。比如下面的例子就是一个解决这个问题的典型方法:
看起来像是能运行,事实上是吗?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个脚本中的可信赖的锁机制。
代码:
运行脚本:
这个lockfile脚本并不是一个独立运行的脚本,你可以在2个终端窗口中进行测试。建立一个锁,给出一个你要锁的文件的名字,要删除锁的话,用-u选项。
运行结果:
分析脚本:
这个脚本是依靠一个锁文件的存在来证明是有锁的,如果加上一个参数的话,会更好。就是一个锁有效的最长时间。
这个脚本对老七而言,实际意义并不大,工作中几乎用不到。自己也仅做了简单的了解。
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: 没有那个文件或目录
分析脚本:
这个脚本是依靠一个锁文件的存在来证明是有锁的,如果加上一个参数的话,会更好。就是一个锁有效的最长时间。
这个脚本对老七而言,实际意义并不大,工作中几乎用不到。自己也仅做了简单的了解。
相关文章推荐
- 第一章:The Missing Code Library--1.在系统路径PATH中寻找程序
- 第一章:The Missing Code Library--7.合法化日期格式
- 第一章:The Missing Code Library--6.合法化浮点数输入
- 第一章:The Missing Code Library--2.合法化输入
- 第一章:The Missing Code Library--11.ANSI颜色序列
- 第一章:The Missing Code Library--8.避免不合要求的echo方法
- 第一章:The Missing Code Library--4.优雅的表示大数
- 第一章:The Missing Code Library--9.一个任意精度浮点计算器
- 第一章:The Missing Code Library--1.在系统路径PATH中寻找程序
- 第一章:The Missing Code Library--7.合法化日期格式
- 第一章:The Missing Code Library--6.合法化浮点数输入
- 第一章:The Missing Code Library--5.合法化整型输入
- 第一章:The Missing Code Library--12.建立一个Shell脚本库
- 第一章:The Missing Code Library--8.避免不合要求的echo方法
- 第一章:The Missing Code Library--4.优雅的表示大数
- 第一章:The Missing Code Library--9.一个任意精度浮点计算器
- 第一章:The Missing Code Library--3.正常化日期格式
- 第一章:The Missing Code Library--13.调试Shell脚本
- 第一章:The Missing Code Library--5.合法化整型输入
- 第一章:The Missing Code Library--2.合法化输入