如何确保 Shell 脚本只有一个实例运行

在做维护的时候,经常要写一些脚本定期检查一些状态信息,而比较糟的时候可能该脚本在执行周期内没完成,接着第二个脚本又开始跑了。如何确保 Shell 脚本只有一个实例运行就成了一个比较有意思的话题。

必需要承认,要做到 100% 的完美可能需要长篇大论才可以做到。如果对于粒度要求不高,这里总结两个粗糙的方法。

一个是在脚本执行的时候判断某个文件的存在,如果不存在,则 touch 创建该文件(该文件看作一个”占座”文件),脚本执行完毕的时候删掉。第二个进程如果启动,判断有该文件存在,则退出或者是 sleep 几秒钟重新判断。这个方法的关键是在删掉”占座”文件的处理方式上。必需要考虑到程序异常、被 Kill 等多个情况。根据需要 trap 搞一下。

trap 和 kill 命令的 -l 参数能够列出你想要的内容

第二个方法是过滤脚本的名字(当然最好把脚本起个独特一点容易过滤的名字),计数,如果存在一个或者多个 instance , 则退出或者 sleep 等待。否则执行脚本。这个方法最简单,但是移植性似乎要差一点,需要考虑不同平台或 Shell 上的表现。

这两个方法都太粗糙了,经不起考究,但是对于 99% 的系统可能都足够用了。反过来说,如果一个系统对于脚本运行的粒度要求非常高,需要考虑到操作的原子性,那么 Shell 或许并不适合完成这个任务。

解决问题就好,过分炫技不可取。

EOF


9 thoughts on “如何确保 Shell 脚本只有一个实例运行

  1. virushuo

    我们现在用的办法是创建一个socket,这样第二个起来的时候就会因为无法bind端口出错。直接退出了。

    Reply
  2. ssnail

    第一个方法也就是lock文件,基本上不会失败,
    第二个方法按理也不会失败,但是现实中也会失败
    这两个方法以前都用过,且都失败过,
    第一种方法后来发现是因为lock的文件被rsync同步所造成,后来改过之后就没有失败过。
    而第二种方法,是在用ps命令查看进程时可能会失败,我那个程序是每分钟都会启动一次的,这样下来一天大概会失败一次,另外ps命令出来的时间也可能会出错。

    Reply
  3. Fenng

    每分钟都启动? 太频繁了,或许你应该直接在程序里多做几个循环,然后重新调度执行时间

    Reply
  4. ssnail

    该程序本身是个死循环,因为是监视程序,cron每分钟都跑这个程序,是为了在死掉之后能立即重起该进程。

    Reply

Leave a Reply

Your email address will not be published. Required fields are marked *