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

如何使Ruby脚本每秒运行一次?,ruby,Ruby,我有一个Ruby脚本,需要每秒运行一次。我正在使用Ruby脚本跟踪目录中文件的修改,并希望该脚本在“实时”时间内跟踪更新 基本上,我想让我的脚本做与在Unix shell上运行“top”相同的事情,在Unix shell中,屏幕大约每秒钟更新一次。Ruby中是否有与JavaScript中相同的setInterval?您可能会发现这个gem很有趣 可以通过以下方式对重复任务进行编码: every 1.second do #your task end 有几种方法可以做到这一点 快速和肮脏的版本

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


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

您可能会发现这个gem很有趣

可以通过以下方式对重复任务进行编码:

every 1.second do
  #your task
end

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

快速和肮脏的版本:

  • 壳牌(韩国):

  • 手表(1):

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

  • 在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 }
    

    您可能想考虑使用RB InCurnices之类的东西来获取文件更改的通知。这样你就可以避免“睡觉”,保持“活着”的感觉


    Guard Gem文档的“高效文件系统处理”部分提供了一些有用的信息:

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

    a = Thread.new { loop { some_method; Thread.stop } }
    b = Thread.new { loop { sleep 1; break unless a.alive?; a.run } }
    
    要停止轮询,请使用
    a.kill
    或确保某些方法在满足某些条件时使用
    thread.kill
    终止自己的线程


    使用这样的两个线程可以确保某些方法至少每秒运行一次,而不管操作的长度如何,而不必进行任何时间检查(当然,在线程调度的粒度范围内)。

    或者您可以使用gem中的TimerTask


    从同一链接中提取的代码

    也许这会有所帮助:(我没有检查它是否也适用于文件修改)我认为它现在可以工作几秒钟。每当设置cron任务时。您无法为cron task.TimerTask设置秒时间,不幸的是,在某些情况下会泄漏线程。
    secondly_loop { my_function }
    
    a = Thread.new { loop { some_method; Thread.stop } }
    b = Thread.new { loop { sleep 1; break unless a.alive?; a.run } }
    
    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