3

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

基本上,我希望我的脚本做与在 Unix shell 上运行“top”相同的事情,屏幕每秒左右更新一次。Ruby 中是否有setInterval类似 JavaScript 的等价物?

4

5 回答 5

15

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

快速和肮脏的版本:

  1. 贝壳(康沃尔语):

    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 }
于 2012-12-09T21:34:07.100 回答
7

无论何时,您都可能会发现这颗宝石很有趣

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

every 1.second do
  #your task
end
于 2012-12-09T21:31:23.580 回答
5

如另一个答案所述, 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_methodThread.kill在满足某些条件时终止其自己的线程。

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

于 2012-12-09T23:24:42.650 回答
3

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

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

于 2012-12-09T23:00:46.897 回答
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

从同一链接中提取的代码

于 2018-04-09T08:55:48.027 回答