Linux 仅当 cron 作业尚未运行时才运行它

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/2366693/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-03 19:48:58  来源:igfitidea点击:

Run cron job only if it isn't already running

linuxbashcronwatchdog

提问by LorenVS

So I'm trying to set up a cron job as a sort of watchdog for a daemon that I've created. If the daemon errors out and fails, I want the cron job to periodically restart it... I'm not sure how possible this is, but I read through a couple of cron tutorials and couldn't find anything that would do what I'm looking for...

因此,我正在尝试将 cron 作业设置为我创建的守护程序的一种看门狗。如果守护程序出错并失败,我希望 cron 作业定期重新启动它......我不确定这有多大可能,但我阅读了几个 cron 教程,但找不到任何可以做我想做的事情我在找...

My daemon gets started from a shell script, so I'm really just looking for a way to run a cron job ONLY if the previous run of that job isn't still running.

我的守护进程是从 shell 脚本启动的,所以我真的只是在寻找一种方法来运行 cron 作业,前提是该作业的上一次运行尚未运行。

I found this post, which did provide a solution for what I'm trying to do using lock files, not I'm not sure if there is a better way to do it...

我找到了这篇文章,它确实为我尝试使用锁定文件做的事情提供了解决方案,但我不确定是否有更好的方法来做到这一点......

Thanks for your help.

谢谢你的帮助。

采纳答案by jjclarkson

I do this for a print spooler program that I wrote, it's just a shell script:

我为我编写的打印假脱机程序执行此操作,它只是一个 shell 脚本:

#!/bin/sh
if ps -ef | grep -v grep | grep doctype.php ; then
        exit 0
else
        /home/user/bin/doctype.php >> /home/user/bin/spooler.log &
        #mailing program
        /home/user/bin/simplemail.php "Print spooler was not running...  Restarted." 
        exit 0
fi

It runs every two minutes and is quite effective. I have it email me with special information if for some reason the process is not running.

它每两分钟运行一次,非常有效。如果由于某种原因进程没有运行,我会通过电子邮件向我发送特殊信息。

回答by Earlz

Don't try to do it via cron. Have cron run a script no matter what, and then have the script decide if the program is running and start it if necessary (note you can use Ruby or Python or your favorite scripting language to do this)

不要尝试通过 cron 来实现。无论如何,让 cron 运行一个脚本,然后让脚本决定程序是否正在运行并在必要时启动它(请注意,您可以使用 Ruby 或 Python 或您喜欢的脚本语言来执行此操作)

回答by Byron Whitlock

As a follow up to Earlz answer, you need a wrapper script that creates a $PID.running file when it starts, and delete when it ends. The wrapper script calls the script you wish to run. The wrapper is necessary in case the target script fails or errors out, the pid file gets deleted..

作为 Earlz 回答的后续,您需要一个包装脚本,该脚本在开始时创建 $PID.running 文件,并在结束时删除。包装器脚本调用您希望运行的脚本。包装器是必要的,以防目标脚本失败或出错,pid 文件被删除..

回答by Zitrax

I would recommend to use an existing tool such as monit, it will monitor and auto restart processes. There is more information available here. It should be easily available in most distributions.

我建议使用现有的工具,例如monit,它将监视和自动重启进程。此处提供更多信息。它应该在大多数发行版中很容易获得。

回答by rsanden

As others have stated, writing and checking a PID file is a good solution. Here's my bash implementation:

正如其他人所说,编写和检查 PID 文件是一个很好的解决方案。这是我的 bash 实现:

#!/bin/bash

mkdir -p "$HOME/tmp"
PIDFILE="$HOME/tmp/myprogram.pid"

if [ -e "${PIDFILE}" ] && (ps -u $(whoami) -opid= |
                           grep -P "^\s*$(cat ${PIDFILE})$" &> /dev/null); then
  echo "Already running."
  exit 99
fi

/path/to/myprogram > $HOME/tmp/myprogram.log &

echo $! > "${PIDFILE}"
chmod 644 "${PIDFILE}"

回答by quezacoatl

You can also do it as a one-liner directly in your crontab:

您也可以直接在 crontab 中将其作为单行:

* * * * * [ `ps -ef|grep -v grep|grep <command>` -eq 0 ] && <command>

回答by Richard Thomas

Consider using pgrep (if available) rather than ps piped through grep if you're going to go that route. Though, personally, I've got a lot of mileage out of scripts of the form

如果您打算走那条路,请考虑使用 pgrep(如果可用)而不是通过 grep 管道传输的 ps。虽然,就个人而言,我从表单的脚本中获得了很多好处

while(1){
  call script_that_must_run
  sleep 5
}

Though this can fail and cron jobs areoften the best way for essential stuff. Just another alternative.

虽然这可能会失败,并cron作业经常必不可少的东西的最佳方式。只是另一种选择。

回答by dbenton

I'd suggest the following as an improvement to rsanden's answer(I'd post as a comment, but don't have enough reputation...):

我建议将以下内容作为对rsanden 答案的改进(我将作为评论发布,但没有足够的声誉......):

#!/usr/bin/env bash

PIDFILE="$HOME/tmp/myprogram.pid"

if [ -e "${PIDFILE}" ] && (ps -p $(cat ${PIDFILE}) > /dev/null); then
  echo "Already running."
  exit 99
fi

/path/to/myprogram

This avoids possible false matches (and the overhead of grepping), and it suppresses output and relies only on exit status of ps.

这避免了可能的错误匹配(以及 grepping 的开销),并且它会抑制输出并且仅依赖于 ps 的退出状态。

回答by Aaron C. de Bruyn

With lockrunyou don't need to write a wrapper script for your cron job. http://www.unixwiz.net/tools/lockrun.html

随着lockrun你不需要写一个包装脚本的cron作业。 http://www.unixwiz.net/tools/lockrun.html

回答by Jess

Use flock. It's new. It's better.

使用flock. 这是新的。更好。

Now you don't have to write the code yourself. Check out more reasons here: https://serverfault.com/a/82863

现在您不必自己编写代码。在此处查看更多原因:https: //serverfault.com/a/82863

/usr/bin/flock -n /tmp/my.lockfile /usr/local/bin/my_script