防止重复运行的 cron 作业

Tom*_*Tom 116 scheduling cron

我已经安排了一个 cron 作业每分钟运行一次,但有时脚本需要超过一分钟才能完成,我不希望这些作业开始“堆积”。我猜这是一个并发问题 - 即脚本执行需要相互排斥。

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

wom*_*ble 156

有几个程序可以自动执行此功能,消除自己执行此操作的烦恼和潜在错误,并通过在幕后使用 flock 来避免过时的锁定问题(如果您只是使用触摸,这是一种风险) . 我过去曾经使用过lockrunlckdo,但现在有flock(1)(在 util-linux 的新版本中)很棒。它真的很容易使用:

* * * * * /usr/bin/flock -n /tmp/fcj.lockfile /usr/local/bin/frequent_cron_job
Run Code Online (Sandbox Code Playgroud)

  • lckdo 将从 moreutils 中删除,现在 flock(1) 在 util-linux 中。该软件包在 Linux 系统中基本上是必需的,因此您应该能够依赖它的存在。用法见下。 (2认同)
  • @Nanne,我必须检查代码才能确定,但​​我有根据的猜测是`-c` 通过外壳运行指定的命令(根据手册页),而“裸”(非`-c `) 形式只是`exec`s 给出的命令。通过 shell 放置一些东西可以让你做类似 shell 的事情(比如运行多个用 `;` 或 `&&` 分隔的命令),但如果你使用不受信任的输入,也会让你受到 shell 扩展攻击。 (2认同)

Phi*_*lds 31

shell 中最好的方法是使用flock(1)

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

  • 我知道这种结构会创建一个排他锁,但我不明白这是如何实现的机制。这个答案中“99”的作用是什么?有人愿意解释一下吗?谢谢! (6认同)
  • 我不能不赞成 fd 重定向的巧妙使用。简直太神奇了。 (2认同)
  • @Javier:并不意味着它不棘手和神秘,只是它被*记录*、棘手和神秘。 (2认同)

Ami*_*mir 25

实际上,flock -n可以使用 代替lckdo*,因此您将使用内核开发人员的代码。

womble 的示例为基础,您将编写如下内容:

* * * * * flock -n /some/lockfile command_to_run_every_minute
Run Code Online (Sandbox Code Playgroud)

BTW,看代码,所有的flocklockrunlckdo做同样的事情,所以它只是一个问题,其中最容易提供给您。


Ami*_*mir 5

现在systemd已经出来了,Linux系统上还有另一种调度机制:

Asystemd.timer

/etc/systemd/system/myjob.service~/.config/systemd/user/myjob.service

[Service]
ExecStart=/usr/local/bin/myjob
Run Code Online (Sandbox Code Playgroud)

/etc/systemd/system/myjob.timer~/.config/systemd/user/myjob.timer

[Timer]
OnCalendar=minutely

[Install]
WantedBy=timers.target
Run Code Online (Sandbox Code Playgroud)

如果当定时器下次激活时服务单元已经激活,则该服务的另一个实例将不会启动。

另一种方法是在启动时启动一次作业,并在每次运行完成后一分钟启动一次作业:

[Timer]
OnBootSec=1m
OnUnitInactiveSec=1m 

[Install]
WantedBy=timers.target
Run Code Online (Sandbox Code Playgroud)