読者です 読者をやめる 読者になる 読者になる

Studio3104::BLOG.new

uninitialized constant Studio3104 (NameError)

ゆるく `my.cnf` の比較などが出来る gem を作った

複数my.cnf を比較して差異を知りたいが、通常のファイル同士の比較(diff) ではわかりにくいしそもそも知りたい情報を得るのはつらい。
ということがあり作成していた書き捨てのスクリプトがあったのだが、整理してテストまで書いて rubygems に放流した。

mycnf | RubyGems.org | your community gem host

studio3104/mycnf · GitHub

mycnf.gem

機能概要

parse

my.cnf のファイルパスを食わせると parse して hash を返す

generate

上記の parse のフォーマットの hash を食わせると my.cnf を文字列で返す

compare

上記の parse のフォーマットの hash を複数食わせると、比較しやすいフォーマットで hash を返す
(ファイルパスを複数食わせて同様の結果を返す compare_files もある)

diff

上記の compare の結果から、差異のあるパラメタのみを select して返す
(ファイルパスを複数食わせて同様の結果を返す diff_files もある)

使い方

こんな感じの my.cnf があったとする。

$ cat /etc/my.cnf.1
[client]
port            = 3306
socket          = /var/lib/mysql/mysql.sock

[mysql]
no_auto_rehash

[mysqld]
datadir         = /var/lib/mysql
port            = 3306
socket          = /var/lib/mysql/mysql.sock
$ cat /etc/my.cnf.2
[client]
port            = 3308
socket          = /var/lib/mysql/mysql.sock

[mysql]
no_auto_rehash
safe-updates

[mysqld]
datadir         = /var/lib/mysql
port            = 3308
socket          = /var/lib/mysql/mysql.sock
parse
MyCnf.parse('/etc/my.cnf.1')
{
   client: {
     port: 3306, socket: '/var/lib/mysql/mysql.sock'
   },
   mysql: {
     no_auto_rehash: ''
   },
   mysqld: {
     datadir: '/var/lib/mysql', port: 3306, socket: '/var/lib/mysql/mysql.sock'
   }
}
generate
MyCnf.generate({
  client: {
    port: 3306,
    socket: '/var/lib/mysql/mysql.sock'
  }
})
[client]
port = 3306
socket = /var/lib/mysql/mysql.sock
compare
MyCnf.compare(MyCnf.parse('/etc/my.cnf.1'), MyCnf.parse('/etc/my.cnf.2'))
MyCnf.compare_files('/etc/my.cnf.1', '/etc/my.cnf.2')
{
  client: {
    port: [ 3306, 3308 ],
    socket: [ '/var/lib/mysql/mysql.sock', '/var/lib/mysql/mysql.sock' ]
  },
  mysql: {
    no_auto_rehash: [ '', '' ],
    safe_updates: [ nil, '' ]
  },
  mysqld: {
    datadir: [ '/var/lib/mysql', '/var/lib/mysql' ],
    port: [ 3306, 3308 ],
    socket: [ '/var/lib/mysql/mysql.sock', '/var/lib/mysql/mysql.sock' ]
  }
}
diff
MyCnf.diff(MyCnf.parse('/etc/my.cnf.1'), MyCnf.parse('/etc/my.cnf.2'))
MyCnf.diff_files('/etc/my.cnf.1', '/etc/my.cnf.2')
{
  client: {
    port: [ 3306, 3308 ]
  },
  mysql: {
    safe_updates: [ nil, '' ]
  },
  mysqld: {
    port: [ 3306, 3308 ]
  }
}

出来ないこと(0.0.1 現在)

暗黙のデフォルト値との比較は出来ない

たとえば、innodb_buffer_pool_size の値が明示されいるものとそうでないものを比較した場合は以下のような結果が返る。

$ cat /tmp/my.a.cnf
[mysqld]
server_id = 1
innodb_buffer_pool_size = 128M
$ cat /tmp/my.b.cnf
[mysqld]
server_id = 2
$ pry
[1] pry(main)> require 'mycnf'
=> true
[2] pry(main)> MyCnf.diff_files('/tmp/my.a.cnf', '/tmp/my.b.cnf')
=> {:mysqld=>{:server_id=>[1, 2], :innodb_buffer_pool_size=>["128M", nil]}}

MySQL 5.6 系において、innodb_buffer_pool_size のデフォルト値は 128MB であるが、そういったデフォルト値を考慮した比較をする実装にはなっていない。
あくまで明示的に記述されているパラメタのみの比較を行う。

!include, !includedir の先に定義してある設定を追いかける

すべてのメソッドにおいて、!include, !includedir の先で定義してあるパラメタを追うことは出来ない。
あくまで引数に与えたファイル及び hash の中だけで完結する範囲で処理を行います。

さて

こういうのって書き捨てて終わっちゃうことが多くて、あとでまた使いたいときに見つからないとかあったりして困ることがある。
ので、まぁこの程度ならすぐまた書けるべって思わなくもないけど、整理して次の機会にもまたすぐに使えるようにしておいた。