如何让Ruby脚本每秒运行一次?
我有一个Ruby脚本,需要每秒运行一次。 我正在使用Ruby脚本来跟踪目录中文件的修改,并希望脚本在“实时”时间内跟踪更新。
基本上,我希望我的脚本能够像在Unix shell上运行“top”一样运行,其中屏幕每隔一秒左右更新一次。 在Ruby中是否存在与Ruby中的setInterval
相同的内容?
有几种方法可以做到这一点。
快速和肮脏的版本:
-
贝壳(kornish):
while :; do my_ruby_script.rb sleep 1 done
-
(1)看:
shell$ watch -n 1 my_ruby_script.rb
这将每秒运行您的脚本并保持终端中显示的最新运行的输出。
-
在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 }
你可能会发现有趣的这个gem
您可以这样编码重复任务:
every 1.second do #your task end
您可能需要考虑使用rb-inotify之类的东西来获取文件更改的通知。 通过这种方式,您可以避免“睡眠”并保持“现场”的感觉。
Guard Gem文档的“高效文件系统处理”部分提供了一些有用的信息: https : //github.com/guard/guard#efficient-filesystem-handling
如另一个答案所述,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在满足某些条件时使用a.kill
杀死自己的线程。
使用这样的两个线程可确保some_method至少每秒运行一次,无论操作的长度如何,无需任何时间检查自己(当然,在线程调度的粒度内)。
或者您可以使用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
从同一链接中提取的代码