我有一个需要每秒运行一次的Ruby脚本。我正在使用Ruby脚本来跟踪目录中文件的修改,并希望脚本在“实时”时间内跟踪更新。
基本上,我希望我的脚本能够像在Unix shell上运行“top”那样运行,其中屏幕每隔一秒更新一次。在Ruby中是否存在与setInterval
相同的内容,就像在JavaScript中一样?
答案 0 :(得分:13)
有几种方法可以做到这一点。
快速和肮脏的版本:
shell(kornish):
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 }
答案 1 :(得分:6)
答案 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
中的TimerTasktimer_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
从同一链接中提取的代码