こんにちは。エンジニアのAraoです。今回は、Rubyで簡易的なログ出力を行う方法と注意点を紹介します。

この記事で扱うこと

唐突ですが、RubyにはLoggerというログを記録するためのクラスがあります。

class Logger (Ruby 2.5.0)

ログの出力先にファイルを指定したり標準出力を指定したり、ログのフォーマットを設定したり日時を記録したり、様々な機能が提供されていますが、この記事ではそこまで高度なものは求めません。 ちょっと時間のかかるプログラムを実行するときに、期待通りに処理が進んでいることを確認できる程度のものを想定します。

bashの場合

こんな感じのスクリプトsample_bash.shを用意しました。3秒おきに0から9までの数字を出力するだけの単純なスクリプトです。数字が確認したいログだと思ってください。

for i in {0..9} ; do
  sleep 3
  echo $i
done

まずは普通に実行してみます。

$ bash sample_bash.sh

3秒おきに数字がコンソールに出力されるはずです。

次に、標準出力を適当なファイルにリダイレクトしてみます。lessコマンドでファイルの中身を表示してから F (Shift + f) と入力すると、ファイルが更新されたときにその更新を自動で読み込みます。刻々と出力されるログファイルを閲覧するときに便利なので覚えておきましょう。ちなみに止めたいときは Ctrl + c で戻れます。

$ bash sample_bash.sh > bash.log &
$ less bash.log

やはり、3秒おきに数字が書き込まれているはずです。

Rubyの場合

bashの場合と同様に、こんな感じのスクリプトsample_ruby.rbを用意しました。機能はbashの場合と同じで、3秒おきに0から9までの数字を出力するだけのスクリプトです。

10.times{|i|
  sleep 3
  puts i
}

まずは普通に実行してみます。

$ ruby sample_ruby.rb

3秒おきに数字がコンソールに出力されるはずです。

次に、標準出力を適当なファイルにリダイレクトしてみます。

$ ruby sample_ruby.rb > ruby.log &
$ less ruby.log

いかがでしょうか。おそらく、3秒おきには数字が書き込まれず、スクリプトの実行が終わるタイミングで0から9までの数字が一度に書き込まれたと思います。これは、Rubyのデフォルトでは標準出力をバッファリングし、ある程度溜まったら、もしくはスクリプトの実行が終わるときにまとめて渡すようになっているためです。

標準出力をバッファリングしないようにするための設定を追加したsample_ruby2.rbを用意しました。

STDOUT.sync = true

10.times{|i|
  sleep 3
  puts i
}
$ ruby sample_ruby2.rb
$ ruby sample_ruby2.rb > ruby2.log &
$ less ruby2.log

普通に実行した場合、適当なファイルにリダイレクトした場合、どちらの場合でも、bashの場合と同様の挙動になることが確認できたと思います。

以上、Rubyで簡易的なログ出力を行う方法と注意点の紹介でした。