如何让Ruby脚本每秒运行一次?

我有一个Ruby脚本,需要每秒运行一次。 我正在使用Ruby脚本来跟踪目录中文件的修改,并希望脚本在“实时”时间内跟踪更新。

基本上,我希望我的脚本能够像在Unix shell上运行“top”一样运行,其中屏幕每隔一秒左右更新一次。 在Ruby中是否存在与Ruby中的setInterval相同的内容?

有几种方法可以做到这一点。

快速和肮脏的版本:

  1. 贝壳(kornish):

     while :; do my_ruby_script.rb sleep 1 done 
  2. (1)看:

     shell$ watch -n 1 my_ruby_script.rb 

    这将每秒运行您的脚本并保持终端中显示的最新运行的输出。

  3. 在ruby:

     while true do_my_stuff sleep 1 end 

这些都遭受同样的问题:如果实际的脚本/函数需要时间来运行,它会使循环运行少于每秒。

这是一个ruby函数,只要函数不超过一秒钟,就会确保函数(几乎)每秒都被调用一次:

 def secondly_loop last = Time.now while true yield now = Time.now _next = [last + 1,now].max sleep (_next-now) last = _next end end 

像这样用它:

 secondly_loop { my_function } 

你可能会发现有趣的这个gem

您可以这样编码重复任务:

 every 1.second do #your task end 

您可能需要考虑使用rb-inotify之类的东西来获取文件更改的通知。 通过这种方式,您可以避免“睡眠”并保持“现场”的感觉。

Guard Gem文档的“高效文件系统处理”部分提供了一些有用的信息: https : //github.com/guard/guard#efficient-filesystem-handling

如另一个答案所述,rb-inotify非常适合这类事情。 如果您不想使用它,那么一个简单的方法是使用线程:

 a = Thread.new { loop { some_method; Thread.stop } } b = Thread.new { loop { sleep 1; break unless a.alive?; a.run } } 

要停止轮询,请使用a.kill或确保some_method在满足某些条件时使用a.kill杀死自己的线程。

使用这样的两个线程可确保some_method至少每秒运行一次,无论操作的长度如何,无需任何时间检查自己(当然,在线程调度的粒度内)。

或者您可以使用Concurrent Ruby gem中的TimerTask

 timer_task = Concurrent::TimerTask.new(execution_interval: 1) do |task| task.execution_interval.times{ print 'Boom! ' } print "\n" task.execution_interval += 1 if task.execution_interval > 5 puts 'Stopping...' task.shutdown end end timer_task.execute 

从同一链接中提取的代码