给shell脚本加锁

Posted 后端技术小黑屋

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了给shell脚本加锁相关的知识,希望对你有一定的参考价值。


在内部测试服务器上,有一个shell脚本用于将csv数据表格转换成Python数据文件。在执行过程中的某一步,由于需要对一些文件进行写操作,所以如果同时有两个人运行了导表程序,则第二个人运行到此步骤时,就会失败并退出,这既拖慢了第一个人的导表速度,而且对第二人的体验也不好(运行了五分钟然后告诉我失败了?黑人问号……)。所以我就想给这个shell脚本加个锁,保证同一时刻只能有一个实例在运行,并及早给出其他用户提示信息。

土办法

最开始想到的是一个土办法:每次shell开始运行,就检测某个特定的“锁文件”是否存在,如果不存在就touch一个;如果存在,则输出错误信息,提示用户稍后重试。

LOCKFILE=/home/xxq/lock_update_check_commit_sh.tmp

if [ -e $LOCKFILE ]
then
   echo "Another user is doing the same thing, please wait!"
   exit 1
else
   touch $LOCKFILE
   chmod 600 $LOCKFILE
fi

另外,在程序运行结束时,需要删除这个临时文件:

rm_lock( )
{
   if [ -e $LOCKFILE ]
   then
       rm -f $LOCKFILE
   fi
 }

但是,程序可能正常结束,也可能在外部被kill掉,或者运行中出了异常而中止,所以除了正常结束之外,对于各种异常情况,何时调用这个rm_lock函数呢?

这里,我用到了一个trap命令,它可以为信号量设置回调命令。

trap 'rm_lock' 1 2 3 9 15

这样一个土“文件锁”就成型了。

flock

但是其实,flock提供了一种更清爽的办法来实现这一功能:

LOCKFILE="/home/xxq/lock_update_check_commit_sh.tmp"

exec 200>$LOCKFILE
flock -n 200 || {
    echo "Another user is doing the same thing,please wait.."
    flock 200 
}

exec那一行将LOCKFILE和文件描述符200以“写”的方式连接起来(不需要LOCKFILE存在),之后flock尝试获得文件描述符200的锁,-n参数表示如果失败则直接fail而不等待。所以这里如果没有获得锁的话,会输出一条提示信息,然后以阻塞的方式等待获得文件描述符200的锁。

最给力的是,在整个shell脚本执行结束时,文件描述符200会关闭,则其上的锁也就会自动释放。这样,就不用上面那种使用trap的方式去处理各种异常!


推荐阅读:




题图: JeongGuHyeok

授权: CC0协议


以上是关于给shell脚本加锁的主要内容,如果未能解决你的问题,请参考以下文章

Python如何调用别人写好的脚本

shell 脚本 片段

用于确保在任何给定时间仅运行一个 shell 脚本的 shell 片段 [重复]

常用python日期日志获取内容循环的代码片段

shell脚本引用expect

Shell脚本切割日志