How do I make a Ruby script run once a second?

2020-05-24 10:45发布

I have a Ruby script that needs to run about one time a second. I am using a Ruby script to keep track of modifications of files in a directory and want the script to track updates in "live" time.

Basically, I want my script to do the same kind of thing as running "top" on a Unix shell, where the screen is updated every second or so. Is there an equivalent to setInterval in Ruby like there is in JavaScript?

标签: ruby
5条回答
欢心
2楼-- · 2020-05-24 11:31

Or you could use TimerTask from the Concurrent Ruby gem

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

Code extracted from the same link

查看更多
\"骚年 ilove
3楼-- · 2020-05-24 11:35

You might want to consider using something like rb-inotify to get notifications of changes of files. This way you can avoid "sleep" and keep the "live" feeling.

There is some useful information at the "Efficient Filesystem Handling" section of the Guard Gem documentation: https://github.com/guard/guard#efficient-filesystem-handling

查看更多
甜甜的少女心
4楼-- · 2020-05-24 11:37

You may find interesting this gem whenever

You can code repeating tasks this way:

every 1.second do
  #your task
end
查看更多
够拽才男人
5楼-- · 2020-05-24 11:38

As stated in another answer, rb-inotify is well suited to this sort of thing. If you don't want to use it, then a simple approach is to use threads:

a = Thread.new { loop { some_method; Thread.stop } }
b = Thread.new { loop { sleep 1; break unless a.alive?; a.run } }

To stop polling, use a.kill or make sure that some_method kills its own thread with Thread.kill when some condition is met.

Using two threads like this ensures that some_method runs at least every second, regardless of the length of the operation, without having to do any time checking yourself (within the granularity of the thread scheduling, of course).

查看更多
再贱就再见
6楼-- · 2020-05-24 11:41

There are a few ways to do this.

The quick-and-dirty versions:

  1. shell (kornish):

    while :; do
       my_ruby_script.rb
       sleep 1
    done
    
  2. watch(1):

    shell$ watch -n 1 my_ruby_script.rb
    

    This will run your script every second and keep the output of the most recent run displayed in your terminal.

  3. in ruby:

    while true
       do_my_stuff
       sleep 1
    end
    

These all suffer from the same issue: if the actual script/function takes time to run, it makes the loop run less than every second.

Here is a ruby function that will make sure the function is called (almost) exactly every second, as long as the function doesn't take longer than a second:

def secondly_loop
    last = Time.now
    while true
        yield
        now = Time.now
        _next = [last + 1,now].max
        sleep (_next-now)
        last = _next
    end
end

Use it like this:

secondly_loop { my_function }
查看更多
登录 后发表回答