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

时间:2012-12-09 21:21:42

标签: ruby

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

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

5 个答案:

答案 0 :(得分:13)

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

快速和肮脏的版本:

  1. shell(kornish):

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

    shell$ watch -n 1 my_ruby_script.rb
    

    这将每秒运行一次脚本并保持终端显示最近一次运行的输出。

  3. 红宝石中的
  4. while true
       do_my_stuff
       sleep 1
    end
    
  5. 这些都遭遇同样的问题:如果实际的脚本/函数需要时间来运行,它会使循环运行少于每秒。

    这是一个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 }
    

答案 1 :(得分:6)

你可能会发现有趣的这个宝石whenever

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

every 1.second do
  #your task
end

答案 2 :(得分:4)

如另一个答案中所述,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在满足某些条件时使用Thread.kill杀死自己的主题。

使用这样的两个线程可以确保some_method至少每秒运行一次,无论操作的长度如何,而不必自行检查(当然,在线程调度的粒度范围内)。

答案 3 :(得分:3)

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

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

答案 4 :(得分:0)

或者您可以使用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

从同一链接中提取的代码