Capistranoでログを標準出力とファイル出力の両方に出力する方法
もっとシンプルにできるやり方があれば教えてくださいませ!
chefを動かしているCapistranoのログをよしなにする必要があり
標準出力とファイル出力の両方に出力することはできないかなと悪戦苦闘した記録になります。
- 参考
capturing output to log file
require 'capistrano'
require 'capistrano/logger'output = '/var/log/capistrano.log'
custom_logger = Capistrano::Logger.new(:output => output)
custom_logger.level = Capistrano::Logger::TRACE
self.logger = custom_logger
まず、こちらの設定で標準出力は行わず、ファイル出力されることを確認。
では合わせて標準出力に出すにはoutputをもうひとつ指定したらよしなにしてくれるだろうと。
custom_logger = Capistrano::Logger.new(:output => output)↓
custom_logger = Capistrano::Logger.new(:output => output, :output => STDOUT)
1つ目のoutput引数が2つ目のoutput引数に上書きされて終わり。
そう簡単にはいかないですよね。
ということでCapistranoの中身を確認するとlog関係は
/lib/capistrano/logger.rbここにありそうだなと。
def initialize(options={})
output = options[:output] || $stderr
if output.respond_to?(:puts)
@device = output
else
@device = File.open(output.to_str, "a")
@needs_close = true
end@options = options
@level = 0
enddef close
device.close if @needs_close
enddef log(level, message, line_prefix=nil)
if level <= self.level
indent = "%*s" % [MAX_LEVEL, "*" * (MAX_LEVEL - level)]
message.each do |line|
if line_prefix
device.puts "#{indent} [#{line_prefix}] #{line.strip}\n"
else
device.puts "#{indent} #{line.strip}\n"
end
end
end
end
putsってメソッドがあればdeviceってのに格納することがわかったので
それを偽装してやればいいんだ。ということがわかります。
config/mydevice.rb
class MyDeviceattr_accessor :buffer
def puts(msg)
STDOUT.puts(msg)
@buffer = @buffer + msg
end
def tty?
return false
end
def initialize
@buffer = ""
end
def clone
end
end
こんな風にSTDOUT(標準出力)と@buffer(ファイル出力のための変数)に出力するようにします。
deploy.rb
require 'capistrano'
require 'capistrano/logger'
load 'config/mydevice'self.logger.device = MyDevice.new
そしてdeploy.rbに上記記述を書くことで、設定が上書きされます。
task :message do
open("/tmp/capistrano.log", "w") {|f| f.write self.logger.device.buffer}
end
こんな感じでmessageを出力するtaskを記載することで
/tmp/capistrano.logへ上書きで出力してくれます。
Perlのツールでもこんなにコードを読んだことはなかったので
どうやって読んでいったらいいかのきっかけになったのと、クラスとかそういうものが
ぼんやりとわかってきたような気がします。