如何正经的实现shell脚本单例运行

发布时间:2021-10-27 16:29:22 作者:小新
来源:亿速云 阅读:254

这篇文章将为大家详细讲解有关如何正经的实现shell脚本单例运行,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。

看起来可行的方法

一个非常简单的思路就是,新的脚本被执行时,先检测当前脚本是否有其他实例正在运行,如果有则直接退出。

runCount=$(ps -ef|grep test.sh | grep -v grep -c) if [ "${runCount}" -ge 1 ] then     echo -e "test.sh already running,num:${runCount}"     exit 1; fi while true do     echo "test.sh run"     sleep 1 done

这里通过ps获取到当前在运行的test.sh脚本数,如果大于1,说明已经有在运行的了。

但是你运行会发现,其程序数量不只是一个。

$ ./test.sh test.sh already running,num:2

惊不惊喜?为什么为这样呢?原因在于,shell脚本中一个命令执行相当于fork了一个进程执行,这里执行的是查找tesh.sh并grep的程序,另外还有一个就是当前运行的脚本程序,这样的方式自然就会出现每次都有两个了。

当然判断条件这里你可以换一下,例如数量大于2,但终归不太好。

文件锁

实际上这种方法你已经在《如何让你的程序同时只有一个在运行》介绍过了,只不过之前是用于编写C/C++程序,而这里是用于shell脚本。

我们来回顾一下,这是一个怎样的过程:

解释一下第一条,为什么一定要确定锁文件中的进程正在运行,因为,有些情况下如果运行的时候退出没有删除该文件,则会导致新的实例永远无法运行。

#!/usr/bin/env bash LOCKFILE=/tmp/test.lock if [ -e ${LOCKFILE} ] && kill -0 `cat ${LOCKFILE}`; then     echo " $0 already running"     exit fi  # 确保退出时,锁文件被删除 trap "rm -f ${LOCKFILE}; exit" INT TERM EXIT #将当前程序进程id写入锁文件 echo $$ > ${LOCKFILE}  # 做你需要的事情 sleep 1000  # 删除锁文件 rm -f ${LOCKFILE}

我们试着运行其中一个,然后另外一个窗口尝试运行:

$ ./test.sh  ./test.sh already running

由于已经有实例在运行,发现新的程序无法运行了。而等旧的脚本运行完之后,新的就可以运行了。

实际上这里面有几个点非常巧妙:

flock

说到锁文件,这里就不得不提flock命令了。没有前面的一些巧妙处理,我们很多时候会很难删除原先创建的锁文件,比如:

因此我们可以考虑使用flock:

#!/usr/bin/env bash LOCK_FILE=/tmp/test.lock exec 99>"$LOCK_FILE" flock -n 99 if [ "$?" != 0 ]; then     echo "$0 already running"     exit 1 fi #脚本要做的其他事情 sleep 1024

解释一下:

因此这里避免了锁没有释放的情况。

另一种做法

查看flock的man手册,我们发现它还有一个例子是这么做的:

[ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en  "$0"  "$0"  "$@" || :

在脚本开头加上上面这么一行就可以了。例如:

#!/usr/bin/env bash [ "${FLOCKER}" != "$0" ] && exec env FLOCKER="$0" flock -en  "$0"  "$0"  "$@" || : #脚本要做的其他事情 sleep 1024

解释一下:如果${FLOCKER}环境变量没有设置,则尝试将脚本本身加锁,如果加锁成功,则运行当前脚本,(并且带上原有的参数),否则的话静默退出。

总结

单例运行本身思路是很简单的,就是探测当前是否有实例在运行,如果有,则退出,但是这里如何判断,却并不是那么容易。

最后,总结一下本文出现的一些该掌握的信息:

关于“如何正经的实现shell脚本单例运行”这篇文章就分享到这里了,希望以上内容可以对大家有一定的帮助,使各位可以学到更多知识,如果觉得文章不错,请把它分享出去让更多的人看到。

推荐阅读:
  1. 单例的实现方式
  2. 单例 (补充) 创建单例的三种方式

免责声明:本站发布的内容(图片、视频和文字)以原创、转载和分享为主,文章观点不代表本网站立场,如果涉及侵权请联系站长邮箱:is@yisu.com进行举报,并提供相关证据,一经查实,将立刻删除涉嫌侵权内容。

shell

上一篇:Linux容器和虚拟机应该如何选择

下一篇:Mysql数据分组排名实现的示例分析

相关阅读

您好,登录后才能下订单哦!

密码登录
登录注册
其他方式登录
点击 登录注册 即表示同意《亿速云用户服务条款》