我每分钟运行一次作业来重新索引我的网站内容。
今天,搜索引擎死机了,当我登录时,发现有数百个由 cron 启动的孤立进程。
是否有另一种方法可以使用某种现有软件,让我每分钟执行一项作业,但如果该作业没有返回(即因为搜索引擎进程失败),它将不会启动另一个实例?
答案1
问题实际上不是出在 cron 上,而是出在你的工作上。
您需要让您的作业与某种描述的锁进行交互。最简单的方法是让它尝试创建一个目录,如果成功则继续,如果不成功则退出。当您的作业完成并退出时,它应该删除目录以准备下一次运行。这里有一个脚本来说明。
#!/bin/bash
function cleanup {
echo "Cleanup"
rmdir /tmp/myjob.lck
}
mkdir /tmp/myjob.lck || exit 1
trap cleanup EXIT
echo 'Job Running'
sleep 60
exit 0
在一个终端中运行它,然后在 60 秒之前在另一个终端中运行它,它将以状态 1 退出。一旦第一个进程退出,您就可以从第二个终端运行它...
编辑:
当我刚刚了解 flock 时,我想我会更新这个答案。
羊群(1)可能更容易使用。在这种情况下flock -n
似乎合适,例如
* * * * * /usr/bin/flock -n /tmp/myAppLock.lck /path/to/your/job
将每分钟运行一次您的作业,但如果 flock 无法获得文件锁定,则会失败。
答案2
一种方法是让您的重新索引脚本创建一个锁定文件,以便它可以检查是否已经有脚本实例正在运行。您还可以添加一些异常处理来查看搜索引擎是否已启动并运行。
一个更复杂的替代方法是使用某种任务排队器,如 Resque 和 Resque-scheduler:
https://github.com/blog/542-introducing-resque
https://github.com/bvandenbos/resque-scheduler#readme
还有 Qu 和 Sidekiq:
https://github.com/bkeepers/qu
https://github.com/mperham/sidekiq
是的,这都是面向 Ruby 的,但您可以用您选择的语言来寻找“类似 resque 的东西”。
答案3
另一种快速设置的方法是在机器启动时启动一个 shell 脚本(cron 可以使用 ' @reboot /path/to/my/script.sh
' 来执行此操作,然后重新启动 cron 来启动它),其中包含类似这样的内容。
#!/bin/sh
/opt/bin/run-site-index
sleep 60
exec $0
脚本会持续运行,并且您只启动了一个脚本 - 即可以同时运行的脚本数量 - 不会超过这个数量。其中的一些智能功能还可以检查索引器是否正在运行,如果没有,则重新启动,或者尝试修复/通知某人该问题。
答案4
我不会使用 cron 来实现这个功能,而是将您的作业构建为一个服务,让它循环运行,并在最后一步休眠 60 秒,或者在整个过程中的各个点以较小的时间间隔更频繁地休眠,以帮助更均匀地分散负载。