我有一个需要每秒运行一次的 Ruby 脚本。我正在使用 Ruby 脚本来跟踪目录中文件的修改,并希望脚本在“实时”时间跟踪更新。
基本上,我希望我的脚本做与在 Unix shell 上运行“top”相同的事情,屏幕每秒左右更新一次。Ruby 中是否有setInterval
类似 JavaScript 的等价物?
我有一个需要每秒运行一次的 Ruby 脚本。我正在使用 Ruby 脚本来跟踪目录中文件的修改,并希望脚本在“实时”时间跟踪更新。
基本上,我希望我的脚本做与在 Unix shell 上运行“top”相同的事情,屏幕每秒左右更新一次。Ruby 中是否有setInterval
类似 JavaScript 的等价物?
有几种方法可以做到这一点。
快速和肮脏的版本:
贝壳(康沃尔语):
while :; do
my_ruby_script.rb
sleep 1
done
手表(1):
shell$ watch -n 1 my_ruby_script.rb
这将每秒运行一次脚本,并在终端中显示最近运行的输出。
在红宝石中:
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-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 至少每秒运行一次,而不管操作的长度如何,而不必花任何时间检查自己(当然,在线程调度的粒度范围内)。
您可能需要考虑使用 rb-inotify 之类的东西来获取文件更改的通知。这样可以避免“睡觉”,保持“活着”的感觉。
Guard Gem 文档的“高效文件系统处理”部分有一些有用的信息:https ://github.com/guard/guard#efficient-filesystem-handling
或者您可以使用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
从同一链接中提取的代码