9

是否有可能仅在它尚未运行时以某种方式执行 rake 任务,我想使用 cron 来执行一些 rake 任务但如果之前的调用未完成,rake 任务不应该启动谢谢

4

5 回答 5

13

我使用lockrun来防止 cron 任务多次运行(这仅在通过相同lockrun调用调用命令时有效,因此如果您需要保护各种调用路径,那么您需要寻找其他方法)。

在您的 crontab 中,您可以像这样调用它:

*/5 * * * * /usr/local/bin/lockrun --lockfile=/var/run/this_task.lockrun -- cd /my/path && RAILS_ENV=production bundle exec rake this:task
于 2011-09-14T02:36:12.500 回答
10

此外,您可以使用锁定文件,但在任务中处理它:

def lockfile
  # Assuming you're running Rails
  Rails.root.join('tmp', 'pids', 'leads_task.lock')
end

def running!
  `touch #{lockfile}`
end

def done!
  `rm #{lockfile}`
end

def running?
  File.exists?(lockfile)
end

task :long_running do
  unless running?
    running!
    # long running stuff
    done!
  end
end

这可能可以提取到某种模块中,但你明白了。

于 2011-10-21T15:25:06.370 回答
5

对此的一般非 rake 特定解决方案是使用 pid 文件作为锁。您可以将 rake 任务包装在一个脚本中,该脚本在运行 rake 时创建此文件,在 rake 完成运行时将其删除,并在开始前检查它。

不确定 rake 是否内置了一些东西,我什么都不知道。

于 2011-09-06T14:02:23.883 回答
2

如果您只是想跳过这个 rake 任务,您还可以使用数据库来存储有关任务进度的信息(例如,当您开始和完成给定任务时更新字段)并在运行每个任务之前检查该信息。

但是,如果您想要类似队列的行为,您可能需要考虑创建一个守护进程来处理任务。该过程非常简单,并为您提供了更多控制权。关于这个有一个非常好的 railscast:Custom Daemon

守护程序方法还将防止在每个任务上再次加载 rails 环境。如果您的 rake 任务很频繁,这将特别有用。

于 2011-09-13T02:33:59.273 回答
1

这是我用于 rails rake 任务的文件锁定的变体。

把它放在你的 rake 任务文件中(在命名空间下,所以它不会与其他 rake 任务重叠):

def cron_lock(name)
  path = Rails.root.join('tmp', 'cron', "#{name}.lock")
  mkdir_p path.dirname unless path.dirname.directory?
  file = path.open('w')
  return if file.flock(File::LOCK_EX | File::LOCK_NB) == false
  yield
end

用法:

cron_lock 'namespace_task_name' do
  # your code
end

完整示例:

namespace :service do
  def cron_lock(name)
    path = Rails.root.join('tmp', 'cron', "#{name}.lock")
    mkdir_p path.dirname unless path.dirname.directory?
    file = path.open('w')
    return if file.flock(File::LOCK_EX | File::LOCK_NB) == false
    yield
  end

  desc 'description'
  task cleaning: :environment do
    cron_lock 'service_cleaning' do
      # your code
    end
  end
end
于 2015-08-25T10:14:24.963 回答