【问题标题】:Rufus-Scheduler, DaemonKit and trapsRufus-Scheduler、DaemonKit 和陷阱
【发布时间】:2014-12-04 21:08:07
【问题描述】:

我使用 Rufus-Scheduler DaemonKit 守护了一个 Ruby 调度程序脚本(使用 Rufus),我试图捕获 TERM 或 INT 信号,让应用程序在退出前尝试保存状态。

DaemonKit 有自己的 trap_state (private) 方法,它在守护程序脚本之前捕获信号,所以即使我有这个块,它也没什么用。

DaemonKit::Application.running! do |config|

  surprise = Surprise.new(interval, frequency, false)
  surprise.start

  config.trap( 'SIGINT' ) do #tried INT and TERM as well
    puts 'Exiting'
    surprise.stop
    File.delete($lock)
  end
end

作为副作用(可能是我的实现中的错误?)在 sigterm 之后 .rufus 锁定文件仍然存在

现在ctrl-c上的行为是这样的

[daemon-kit]: DaemonKit (0.3.1) booted, now running surprise
log writing failed. can't be called from trap context
[daemon-kit]: Running signal traps for INT
log writing failed. can't be called from trap context
[daemon-kit]: Running shutdown hooks
log writing failed. can't be called from trap context
[daemon-kit]: Shutting down surprise

启动方法是一个非常简单的时间表

def start

@scheduler = Rufus::Scheduler.new(:lockfile =>  $lock)

@scheduler.every '1d', :first_at => @first, :overlap => false do |job|
  ... # some work
end

 @scheduler.join
end

def stop
  # save state
  @scheduler.shutdown
end

【问题讨论】:

  • 抱歉,rufus-scheduler 3.x 中没有陷阱(rufus-scheduler 2.x 有一个,但仅限于其特殊的 SignalScheduler 实现)。您确定您的File.delete($lock) 线路已到达吗?你确定如果达到它会成功吗?在你的陷阱末端放置一个puts 'Exited'... 狼栅栏。
  • @jmettraux 呃,我很愚蠢,我把 DaemonKit 和 Rufus 混为一谈了。这是 DaemonKit 捕获 TERM,我的错
  • 那么请更新您的解释。提前致谢!
  • @jmettraux 是的,完成了。我也发现了问题。

标签: ruby rufus-scheduler daemons


【解决方案1】:

所以这很简单,我需要在启动方法中运行调度程序之前配置陷阱过程(或在我的情况下为块)。现在感觉不是很聪明,但以下代码按预期工作。作为参考,set_trap 在 DK 中是私有的,但公共陷阱方法会覆盖 DK 启动时附带的默认值。

DaemonKit::Application.running! do |config|

  surprise = Surprise.new(interval, frequency, false)

  config.trap("TERM") { surprise.stop }
  config.trap( "INT" ) { surprise.stop }

  surprise.start
end

有趣的是,我在启动时看到了我以前没有注意到的这条线

[daemon-kit]: Trapping SIGINT signals not supported on this platform

INT 和 TERM 都可以工作

【讨论】:

  • 我知道,在 Surprise#start 中,您调用 Scheduler#join 会阻塞正在运行的代码,并且从未设置过以下陷阱。这就是为什么在这个版本中它可以工作的原因。
【解决方案2】:

查看您自己的答案,以及您粘贴的以下代码:

def start
  @scheduler = Rufus::Scheduler.new(:lockfile =>  $lock)
  # ...
  @scheduler.join # <- NOT NEEDED
end

DaemonKit 的 DaemonKit::Application.running! 块实际上永远不会完成运行,因此您可以安全地跳过在任何线程上调用 #join

我们应该努力使这个用例更加清晰,因为我希望看到它更广泛地用于这种工作。

【讨论】:

  • 谢谢!当我在 DK 之前单独使用 Rufus 时,这可能是剩余的。我什么时候需要加入线程?
  • 在一个普通的 Ruby 项目中,您需要这样做。 DaemonKit 抽象出保持脚本正常运行的需要。它会不择手段地让你的进程保持活力和运行。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-07-25
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多