LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1505|回复: 4

如何在Shell中设置文件锁避免脚本重复执行

[复制链接]
发表于 2009-10-22 12:40:18 | 显示全部楼层 |阅读模式
最近在发现过一次监控脚本挂住的问题,就整理了此文,希望对有需要的朋友一些借鉴:

在 Bash Shell 中的实现:
  1. # This is to examine whether the lockfile existed
  2. [ -f "${0}.lock" ] && exit -1
  3. # Create the lock file
  4. lockfile ${0}.lock
  5. # Your code here!
  6. # Release the lock file manually
  7. rm -f ${0}.lock
复制代码

Python 和 Perl 中的实现样例请参考原文 [color="Blue"]http://planet.admon.org/

实现此目的是避免同一个脚本重复执行引起的进程积累,导致大量系统资源被消耗掉。 在 crontab 和 系统监控中尤其要注意这个问题。 以避免对线上环境造成影响。

发表于 2009-10-22 13:25:36 | 显示全部楼层
Sorry I cannot type Chinese now.

It is a good tip, but lockfile is not always available, especially in embedded systems.

I normally rename the file the script will work on to get the lock. For example
  1. if mv foo.log foo.log.$$; then
  2.     do something on foo.log.$$
  3. else
  4.     exit 1
  5. fi
复制代码
mv command is atom operation in shell.
回复 支持 反对

使用道具 举报

发表于 2009-10-22 22:31:19 | 显示全部楼层
  1. lock_on()
  2. {
  3.     local f=$1
  4.     local freefd=6  ## do not use fd 5
  5.     ## make sure the file be there
  6.     mkdir -p "$( dirname $f )"
  7.     touch "$f"
  8.     ## find a free fd
  9.     while (( freefd <= 9 )); do
  10.         [[ -L /dev/fd/$freefd ]] || break
  11.         (( freefd++ ))
  12.     done
  13.     (( freefd == 10 )) && return 1
  14.     ## open the lock file
  15.     eval "exec $freefd< "$f""
  16. }
  17. is_locked()
  18. {
  19.     local f=$1
  20.     fuser "$f" &> /dev/null
  21. }
  22. lock="/tmp/.$( basename $0 ).lock"
  23. is_locked "$lock" && exit 1
  24. lock_on "$lock"
  25. ## do something here
复制代码
回复 支持 反对

使用道具 举报

发表于 2009-10-23 10:50:09 | 显示全部楼层
the is_locked() 代码不错,第一次见到 fuser,谢谢。
不过 lock_on() 代码有问题,从得到有效的 freefd 到上锁,不是原子操作,没有解决重入问题。

mv 或 ln,才是解决脚本重入的王道。
回复 支持 反对

使用道具 举报

 楼主| 发表于 2009-10-23 11:02:23 | 显示全部楼层
感谢几位指点。
huan大的shell功底,小弟有望尘莫及的感觉,我的再研究下那个函数集了。--cax
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表