防止重复的cron作业运行

我已经安排了一个cron工作来运行每一分钟,但有时脚本需要一分多钟才能完成,我不希望这些工作开始“叠加”在一起。 我想这是一个并发问题 – 即脚本执行需要相互排斥。

为了解决这个问题,我使脚本查找了一个特定文件(“ lockfile.txt ”)的存在,如果存在,则退出;如果不存在,则touch它。 但这是一个非常糟糕的信号量! 有一个我应该知道的最佳做法吗? 我应该写一个守护进程吗?

    有几个程序可以自动执行此function,从而避免了自己做这件事的烦恼和潜在的错误,也避免了在幕后使用群集的陈旧locking问题(如果您只是使用触摸,这是一个风险) 。 我过去使用过lockrunlckdo ,但现在有lckdo (1)(在util-linux的新版本中),这非常棒。 这非常容易使用:

     * * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job 

    最好的方法是用shell (1)

     ( flock -x -w 5 99 ## Do your stuff here ) 99>/path/to/my.lock 

    其实, flock -n可以用来代替lckdo *,所以你将会使用内核开发者的代码。

    build立在womble的例子 ,你会写如下的东西:

     * * * * * flock -n /some/lockfile command_to_run_every_minute 

    顺便说一句,看着代码,所有的flocklockrunlckdo做的是完全一样的东西,所以这只是你最容易得到的问题。

    *由于在编写本文时我的名誉,我既不能编辑也不能评论以前的答案,所以我必须把它作为一个单独的答案来写。

    您可以使用locking文件。 脚本启动时创build此文件,并在完成时删除它。 脚本在运行主例程之前,应该检查locking文件是否存在,并相应地执行。

    Unix系统中的初始化文件和许多其他应用程序和实用程序使用了锁文件。

    这也可能是你做错事的迹象。 如果你的工作经常发生,那么也许你应该考虑把它变成一个守护进程的程序。

    如果您希望脚本等待上一次运行完成,您还没有指定。 通过“我不希望工作开始”叠加“彼此”,我想你是暗示你想脚本退出,如果已经运行,

    所以,如果你不想依赖lckdo或类似的,你可以这样做:

     PIDFILE=/tmp/`basename $0`.pid if [ -f $PIDFILE ]; then if ps -p `cat $PIDFILE` > /dev/null 2>&1; then echo "$0 already running!" exit fi fi echo $$ > $PIDFILE trap 'rm -f "$PIDFILE" >/dev/null 2>&1' EXIT HUP KILL INT QUIT TERM # do the work 

    如果以前的cron守护进程仍在运行,您的cron守护进程不应该调用作业。 我是一个cron守护进程dcron的开发者,我们特别试图阻止这个。 我不知道Vixie cron或其他守护进程如何处理这个问题。

    我创build了一个jar来解决像重复的crons运行的问题可能是java或shell cron。 只需在Duplicates.CloseSessions(“Demo.jar”)中传递cron名称,将会search并除去当前cron的existng pid。 我已经实现了这个东西的方法。 String proname = ManagementFactory.getRuntimeMXBean()。getName(); String pid = proname.split(“@”)[0]; System.out.println(“当前PID:”+ PID);

      Process proc = Runtime.getRuntime().exec(new String[]{"bash","-c"," ps aux | grep "+cronname+" | awk '{print $2}' "}); BufferedReader stdInput = new BufferedReader(new InputStreamReader(proc.getInputStream())); String s = null; String killid=""; while ((s = stdInput.readLine()) != null ) { if(s.equals(pid)==false) { killid=killid+s+" "; } } 

    然后再用shell命令杀死killidstring

    我会build议使用运行一个命令 – 比处理锁简单得多。 从文档:

    run-one是一个包装脚本,只运行一个具有唯一参数集的命令的唯一实例。 这对于cronjobs来说是非常有用的,因为你一次只需要运行一个副本。

    run-this-one就像run-one一样,除了它将使用pgrep和kill来查找和终止用户拥有的任何正在运行的进程并匹配目标命令和参数。 请注意,在试图杀死匹配的进程之前,运行这个人将会阻塞,直到所有匹配的进程都死亡。

    run- one-像运行一样运行,除了COMMAND退出(零或非零)时重新运行“COMMAND [ARGS]”。

    保持一个跑步跑步的别名。

    直到成功运行就像运行一样 – 除了它重新生成“COMMAND [ARGS]”,直到COMMAND成功退出(即退出零)为止。

    一直运行,直到失败运行完全像运行一样,除了它重新命令“命令[ARGS]”,直到命令退出失败(即退出非零)。