1秒間に約1回実行する必要があるRubyスクリプトがあります。Rubyスクリプトを使用してディレクトリ内のファイルの変更を追跡しており、スクリプトで「ライブ」時間の更新を追跡したいと考えています。
基本的に、スクリプトでUnixシェルで「top」を実行するのと同じようなことを実行して、画面が1秒ごとに更新されるようにします。setInterval
JavaScriptにあるようなRubyに相当するものはありますか?
1秒間に約1回実行する必要があるRubyスクリプトがあります。Rubyスクリプトを使用してディレクトリ内のファイルの変更を追跡しており、スクリプトで「ライブ」時間の更新を追跡したいと考えています。
基本的に、スクリプトでUnixシェルで「top」を実行するのと同じようなことを実行して、画面が1秒ごとに更新されるようにします。setInterval
JavaScriptにあるようなRubyに相当するものはありますか?
これを行うにはいくつかの方法があります。
クイックアンドダーティバージョン:
シェル(コーニッシュ):
while :; do
my_ruby_script.rb
sleep 1
done
watch(1):
shell$ watch -n 1 my_ruby_script.rb
これにより、スクリプトが1秒ごとに実行され、最新の実行の出力がターミナルに表示されたままになります。
ルビーで:
while true
do_my_stuff
sleep 1
end
これらはすべて同じ問題に悩まされています。実際のスクリプト/関数の実行に時間がかかる場合、ループの実行は1秒未満になります。
これは、関数が1秒より長くかからない限り、関数が(ほぼ)正確に毎秒呼び出されることを確認する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 } }
ポーリングを停止するには、some_methodを使用するか、何らかの条件が満たされたときにa.kill
some_methodが自身のスレッドを強制終了することを確認します。Thread.kill
このように2つのスレッドを使用すると、操作の長さに関係なく、some_methodが少なくとも毎秒実行され、自分でチェックする必要がなくなります(もちろん、スレッドスケジューリングの粒度の範囲内で)。
rb-inotifyのようなものを使用して、ファイルの変更の通知を取得することを検討することをお勧めします。このようにして、「睡眠」を避け、「生きている」感覚を保つことができます。
Guard Gemドキュメントの「効率的なファイルシステム処理」セクションにいくつかの有用な情報があります:https ://github.com/guard/guard#efficient-filesystem-handling
または、 ConcurrentRubygemの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
同じリンクから抽出されたコード