share facebook facebook2 twitter menu hatena pocket slack

2013.06.29 SAT

RubyでRDSのログをログの監視用にダウンロード

鈴木 宏康

WRITTEN BY鈴木 宏康

以前、下記でRubyのSDKを利用したRDSのログのダウンロード方法を紹介しました。

RubyでRDSのログ(すべてのファイル)をダウンロード

今回は(似てるのですが)、下記のログのチェックという観点でスクリプトを作ってみました。

  • RDS側のログが更新された場合のみ最新のログファイル(“mysql-general.log”など)をダウンロードする。
  • ログの更新の判断は”last_written”の時刻を比較する。
  • RDS側のログのローテーションのタイミングとダウンロードのタイミングで抜けてしまうログをフォローするために、ログローテーション時には一世代前のログ(“mysql-general.old”など)もダウンロードする。
  • 最新のものはログのサイズが減少したらローテーションしたと判断する。

作成したスクリプトは下記の通りです。


#!/usr/bin/ruby

require 'rubygems'
require 'aws-sdk'

# 初期設定
AWS.config({ :region => 'ap-northeast-1' })
db_instance_identifier = 'suzlab'
filename = 'general/mysql-general.log'
file_prefix = '/tmp/general_mysql-general'

# 最新のログファイルの"last_written"を保存するファイルの作成
if !File.exists?(file_prefix + '.last_written') then
open(file_prefix + '.last_written', 'w').write('0')
end
# 最新のログファイルの"size"を保存するファイルの作成
if !File.exists?(file_prefix + '.size') then
open(file_prefix + '.size', 'w').write('0')
end

client = AWS::RDS.new.client

# 前回チェック時から更新された最新のログファイルを取得
log_files = client.describe_db_log_files({
:db_instance_identifier => db_instance_identifier,
:filename_contains => filename,
:file_last_written => open(file_prefix + '.last_written', 'r').read.to_i + 1
})

# 該当ログファイルが無ければ終了
if log_files.describe_db_log_files.size == 0 then
exit
end

# 最新のログファイルのダウンロードと更新
additional_data_pending = true
marker = '0:0'
while additional_data_pending do
log = client.download_db_log_file_portion({
:db_instance_identifier => db_instance_identifier,
:log_file_name => filename,
:marker => marker
})
File.open(file_prefix + '.log.tmp', "a") do |io|
if !log.log_file_data.nil? then
io.print(log.log_file_data)
end
end
additional_data_pending = log.additional_data_pending
marker = log.marker
end
File.rename(file_prefix + '.log.tmp', file_prefix + '.log')

# ローテーションのチェック
if open(file_prefix + '.size', 'r').read.to_i > log_files.describe_db_log_files[0].size then

# 一世代前のログファイルを取得
log_files = client.describe_db_log_files({
:db_instance_identifier => db_instance_identifier,
:filename_contains => filename,
})
log_files.describe_db_log_files.sort! { |a, b| a.last_written <=> b.last_written }
log_files.describe_db_log_files.reverse!

# 一世代前のログファイルのダウンロードと更新
additional_data_pending = true
marker = '0:0'
while additional_data_pending do
log = client.download_db_log_file_portion({
:db_instance_identifier => db_instance_identifier,
:log_file_name => log_files.describe_db_log_files[1].log_file_name,
:marker => marker
})
File.open(file_prefix + '.old.tmp', "a") do |io|
if !log.log_file_data.nil? then
io.print(log.log_file_data)
end
end
additional_data_pending = log.additional_data_pending
marker = log.marker
end
File.rename(file_prefix + '.old.tmp', file_prefix + '.old')

end

# "last_written"と"size"を更新(ファイルに出力)
open(file_prefix + '.last_written', 'w').write(log_files.describe_db_log_files[0].last_written)
open(file_prefix + '.size', 'w').write(log_files.describe_db_log_files[0].size)

実行すると下記のようにログなどのファイルが出力されます。


# ll /tmp/
-rw-r--r-- 1 root root 13 6月 27 13:44 2013 general_mysql-general.last_written
-rw-r--r-- 1 root root 55086 6月 27 13:44 2013 general_mysql-general.log
-rw-r--r-- 1 root root 75503 6月 27 13:00 2013 general_mysql-general.old
-rw-r--r-- 1 root root 5 6月 27 13:44 2013 general_mysql-general.size

こちらの記事はなかの人(suz-lab)監修のもと掲載しています。
元記事は、こちら

鈴木 宏康

鈴木 宏康

愛知県生まれ。東京工業大学大学院修士課程修了。在学時より、ベンチャー企業でインターネットに関する業務に携わり、現在はクラウド(主にAmazon Web Services)上での開発・運用を軸とした事業の、業務の中心として活躍。