如何避免shell脚本被同时运行多次

转自:http://www.etwiki.cn/linux/2786.html

比如说有一个周期性(cron)备份mysql的脚本,或者rsync脚本,

如果出现意外,运行时间过长,
很有可能下一个备份周期已经开始了,当前周期的脚本却还没有运行完,
显然我们都不愿意看到这样的情况发生。

其实只要对脚本自身做一些改动,就可以避免它被重复运行。


#!/bin/bash

LOCK_NAME="/tmp/my.lock"
if [[ -e $LOCK_NAME ]] ; then
echo "re-entry, exiting"
exit 1
fi

### Placing lock file
touch $LOCK_NAME
echo -n "Started..."

### 开始正常流程
### 正常流程结束

### Removing lock
rm -f $LOCK_NAME

echo "Done."
 

当脚本开始运行时, 创建 /tmp/my.lock文件,
这时如果再次运行此脚本,发现存在my.lock,就退出,
脚本运行结束时删除这个文件。

大多数情况下,这样做都没有什么问题。
意外1) 如果同时运行二次此脚本, 二个进程都会发现my.lock不存在,然后都可以继续执行。
意外2) 如果脚本在运行过程中意外退出, 没有来得及删除 my.lock文件, 那么就悲剧了。

修改如下:


#!/bin/bash

LOCK_NAME="/tmp/my.lock"
if ( set -o noclobber; echo "$$" > "$LOCK_NAME") 2> /dev/null; 
then
trap 'rm -f "$LOCK_NAME"; exit $?' INT TERM EXIT

### 开始正常流程
### 正常流程结束

### Removing lock
rm -f $LOCK_NAME
trap - INT TERM EXIT
else
echo "Failed to acquire lockfile: $LOCK_NAME." 
echo "Held by $(cat $LOCK_NAME)"
exit 1
fi



echo "Done."
 

set -o noclobber 的意思:


If set, bash does not overwrite an existing file with the >, >&, and <> redirection operators.
 

这样就能保证my.lock只能被一个进程创建出来。比touch靠谱多了。

trap 可以捕获各种信号,然后做出处理:
INT 用来处理 ctrl+c取消脚本执行的情况。
TERM 用来处理 kill -TERM pid 的情况。
EXIT 不清楚

另外,对于 kill -9 无效。。

还记得N年前,在php群里面,草人也问过这个问题,
我们给的答案是 ps aux|grep filename |wc -l ,哈哈,真2。

  • 2
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值