【问题标题】:How do I make a Ruby script run once a second?如何让 Ruby 脚本每秒运行一次?
【发布时间】:2018-04-09 16:55:48
【问题描述】:

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

基本上,我希望我的脚本做与在 Unix shell 上运行“top”相同的事情,屏幕大约每秒更新一次。 Ruby 中是否有与 JavaScript 中相同的 setInterval

【问题讨论】:

标签: ruby


【解决方案1】:

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

快速和肮脏的版本:

  1. 贝壳(kornish):

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

    shell$ watch -n 1 my_ruby_script.rb
    

    这将每秒运行一次您的脚本,并将最近一次运行的输出显示在您的终端中。

  3. 在红宝石中:

    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 }

【讨论】:

    【解决方案2】:

    你可能会觉得这个宝石很有趣whenever

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

    every 1.second do
      #your task
    end
    

    【讨论】:

    • 我认为它现在可以工作几秒钟。每当设置 cron 任务时。您无法为 cron 任务设置秒时间。
    【解决方案3】:

    正如另一个答案中所述, 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 至少每秒运行一次,而不管操作的长度如何,而不必花任何时间检查自己(当然是在线程调度的粒度范围内)。

    【讨论】:

      【解决方案4】:

      您可能需要考虑使用类似 rb-inotify 的东西来获取文件更改的通知。这样可以避免“睡觉”,保持“活着”的感觉。

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

      【讨论】:

        【解决方案5】:

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

        从同一链接中提取的代码

        【讨论】:

        • 不幸的是,TimerTask 在某些情况下会泄漏线程。
        猜你喜欢
        • 2016-07-24
        • 2022-01-11
        • 2013-02-23
        • 2018-10-26
        • 2013-02-04
        • 2018-03-06
        • 1970-01-01
        • 2013-04-02
        • 1970-01-01
        相关资源
        最近更新 更多