ぎょーぼのぶろぐ

IT系の話を書いていくブログです。今はRubyの勉強中。

【Ruby】MySQL に接続してみる その2

前置き

【Ruby】MySQL に接続してみる その1 - ぎょーぼのぶろぐ の記事の続きです。

前回、MySQL側のデータの準備を行いましたので、今回は、Ruby側から MySQL に接続して、データを参照してみます。

MySQL に接続するための gem をインストールする。

Ruby から MySQL へ接続するためには、Ruby用の MySQL クライアントが必要です。

2020/11/18 時点で、いろいろ種類があるみたいですが、「MySQL2」という gem が最も使われているようなので、こちらを使用します。

  • 一番それっぽい名前の「MySQL」gem は、エラーでインストールできませんでした。gem のアップデートも 2013年でストップしているので、皆さん「MySQL2」へ移っているものと思われます。

「MySQL2」gem のインストールは、gem install コマンドを使えば OK です。

> gem install mysql2

引数なしでインストールすると、バージョンは 「mysql2 (0.5.3 x64-mingw32)」となりました。 *1 ・・・メジャーバージョンが 0 なのはなんでだろ?

Ruby コードから、MySQL のデータを取得してみる

「Mysql2」 gem の使い方は、製作者の方が github 上に公開しています。

GitHub - brianmario/mysql2: A modern, simple and very fast Mysql library for Ruby - binding to libmysql

こちらを参考に、テーブルのデータを取得して表示するだけの、単純な Ruby のコードを書いてみます。手順としては、、、

  1. mysql2 を require する。
  2. Mysql2::Client.new でコネクションオブジェクトを生成する。
  3. コネクションオブジェクトの query メソッドに SQL文を送って、結果を取得する。
  4. 結果を表示

実際のコードは下のような感じです。ファイル名は「mysql_test.rb」です。

require 'mysql2'

client = Mysql2::Client.new(host: 'localhost', username: 'gyobo', password: 'password', encoding: 'utf8mb4', database: 'world')

results= client.query('select * from country;')

results.each do |row|
    puts "ID : #{row["id"]}, Name: #{row["name"]}"
end

これで実行してみると・・・下のようにエラーが出てしまいます。

>ruby mysql_test.rb
Traceback (most recent call last):
        3: from mysql_test.rb:3:in `<main>'
        2: from mysql_test.rb:3:in `new'
        1: from C:/Ruby/Ruby26-x64/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3-x64-mingw32/lib/mysql2/client.rb:90:in `initialize'
 (Mysql2::Error)64/lib/ruby/gems/2.6.0/gems/mysql2-0.5.3-x64-mingw32/lib/mysql2/client.rb:90:in `connect': Authentication plugin 'caching_sha2_password' cannot be loaded: ?w?肳?ꂽ???W???[??????????܂???B

エラーの原因:「mysql2」gem が caching_sha2_password に対応してないから

ポイントは、エラー文言の中の「Authentication plugin 'caching_sha2_password' cannot be loaded」の部分です。認証プラグイン'caching_sha2_password'がロードできない・・・

MySQL は、ユーザー認証の際に「認証プラグイン」というのを使うそうです。MySQL 5 のときは「mysql_native_password」がデフォルトだったのですが、MySQL 8 になってから「caching_sha2_password」というのが追加され、ユーザーの新規作成時、認証プラグインを指定しない場合は、デフォルトで「caching_sha2_password」となるそうです。そして、、、MySQLクライアントで「caching_sha2_password」に対応しているものが Ruby ではまだ無い(2020年11月現在)、、、ということみたいです。

「caching_sha2_password」に対応しているMySQLクライアントは、以下のリンク先で確認できます。

MySQL :: MySQL 8.0 Reference Manual :: 2.11.4 Changes in MySQL 8.0

このため、Ruby から MySQL 8 へ接続するためには、MySQL に接続するユーザーの認証プラグインをあらかじめ、「mysql_native_password」にしておく必要があります。。。

というわけで、MySQL にログインして、ユーザーの認証プラグインを「mysql_native_password」に変更します。

mysql> SELECT user, plugin FROM mysql.user WHERE user='gyobo';
+------------------+-----------------------+
| user             | plugin                |
+------------------+-----------------------+
| gyobo            | caching_sha2_password |
+------------------+-----------------------+
1 rows in set (0.00 sec)

mysql> ALTER USER gyobo@localhost IDENTIFIED WITH mysql_native_password BY 'password';
Query OK, 0 rows affected (0.01 sec)

mysql> SELECT user, plugin FROM mysql.user WHERE user='gyobo';
+------------------+-----------------------+
| user             | plugin                |
+------------------+-----------------------+
| gyobo            | mysql_native_password |
+------------------+-----------------------+
1 rows in set (0.00 sec)

こうして再度、実行してみると、、、

>ruby mysql_test.rb
ID : 1, Name: 日本
ID : 2, Name: アメリカ
ID : 3, Name: イギリス

データを取得することができました。

補足?蛇足?

ネットでいろいろ調べてみると、MySQL でユーザーを作成する際のデフォルトの認証プラグインを「mysql_native_password」に変更したらいい、という記事も見かけました。が、個人的にはそれはしない方がいいと思います。

理由は、「caching_sha2_password」 の方が、「mysql_native_password」よりもセキュリティ面では良いらしいから。

基本は、「caching_sha2_password」を使うようにして、今回のように「caching_sha2_passwordが対応してないから使えない」という場合に、必要な範囲で「mysql_native_password」に変更するようにすべき、と思われます。

*1:2020年11月18日現在です。

【Ruby】MySQL に接続してみる その1

前置き

Ruby から、MySQL データベースに接続してみます。

今回の環境は、Windows10、Ruby 2.6.6、MySQL 8.0.22 です。

C:\Users\gyobo>ruby --version
ruby 2.6.6p146 (2020-03-31 revision 67876) [x64-mingw32]
C:\Users\gyobo>mysql --version
mysql  Ver 8.0.22 for Win64 on x86_64 (MySQL Community Server - GPL)

MySQL の準備

Windows版の MySQL のインストールについては、ネットに様々、情報が出ていますので、そちらを参考にセットアップしてください。例えばこことか。Windows 版 MySQL インストール手順 - Qiita

セットアップするのは、「MySQL Community Server」です。

導入の際、「MySQL for Visual Studio」とか「Connector/Python」とか、使わないものは入れないでいいです。「Workbench」はコマンド苦手な人には便利なので、入れていいと思います。

インストール後、コマンドプロンプト上で、mysql --version としたときにバージョン情報が出ない場合は、パスがちゃんと通ってませんので、環境変数のパスを追加しましょう。デフォルトでインストールしているなら、C:\Program Files\MySQL\MySQL Server 8.0\bin です。

MySQL 側の準備

Ruby でアクセスする情報を、MySQL側に準備しておきます。

今回は、インストール時に「gyobo」の名前でユーザーを作っておいたので、そのユーザーでログインし、作っていきます。

とりあえず、ログインして・・・

C:\Users\gyobo>mysql -u gyobo -p
Enter password: ********
Welcome to the MySQL monitor.  Commands end with ; or \g.
Your MySQL connection id is 8
Server version: 8.0.22 MySQL Community Server - GPL

Copyright (c) 2000, 2020, Oracle and/or its affiliates. All rights reserved.

Oracle is a registered trademark of Oracle Corporation and/or its
affiliates. Other names may be trademarks of their respective
owners.

Type 'help;' or '\h' for help. Type '\c' to clear the current input statement.

world という名前のデータベースを作ってみます。今回はこだわりがないので、名前だけ指定して生成します。

mysql> CREATE DATABASE world;
Query OK, 1 row affected (0.01 sec)

mysql> SHOW DATABASES;
+--------------------+
| Database           |
+--------------------+
| information_schema |
| mysql              |
| performance_schema |
| sys                |
| world              |
+--------------------+
5 rows in set (0.00 sec)

MySQL 8.0 では、デフォルトの文字コードutf8mb4、照合順序は utf8mb4_0900_ai_ci になっています。

mysql> SELECT @@character_set_database, @@collation_database;
+--------------------------+----------------------+
| @@character_set_database | @@collation_database |
+--------------------------+----------------------+
| utf8mb4                  | utf8mb4_0900_ai_ci   |
+--------------------------+----------------------+
1 row in set (0.00 sec)

utf8mb4 は、絵文字などの4バイト文字が使える文字コードです。昔、タブレットからも入力があるシステムなのに、誤って utf8 でデータベース、テーブルを作ってしまって、開発の後半になってから「絵文字どうしよう・・・」になった思い出がありますが、デフォルトになってくれたので、その心配はなくなっています。

照合順序は、文字の比較や並べ替えに使用するルールです。utf8mb4_0900_ai_ci は、文字コードutf8mb4 で、Accent Insensitive(アクセント無視)、Case Insensitive(大文字小文字無視)、ということになります。

続いて、テーブルを作成します。USE句を使って、デフォルトのデータベースを world に変更して、CREATE TABLE文でテーブルを作成します。今回は、キーとか制約、インデックスのこだわりもないので、列名と型の指定だけで作成します。

mysql> USE world
Database changed
mysql> CREATE TABLE country(id INT, name VARCHAR(20));
Query OK, 0 rows affected (0.05 sec)

mysql> DESC country;
+-------+-------------+------+-----+---------+-------+
| Field | Type        | Null | Key | Default | Extra |
+-------+-------------+------+-----+---------+-------+
| id    | int         | YES  |     | NULL    |       |
| name  | varchar(20) | YES  |     | NULL    |       |
+-------+-------------+------+-----+---------+-------+
2 rows in set (0.01 sec)

適当に、データも入れておきます。

mysql> INSERT INTO country(id, name) VALUES (1, '日本');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO country(id, name) VALUES (2, 'アメリカ');
Query OK, 1 row affected (0.01 sec)

mysql> INSERT INTO country(id, name) VALUES (3, 'イギリス');
Query OK, 1 row affected (0.01 sec)

mysql> select * from country;
+------+----------+
| id   | name     |
+------+----------+
|    1 | 日本     |
|    2 | アメリカ |
|    3 | イギリス |
+------+----------+
3 rows in set (0.00 sec)

このデータに、Ruby のコードからアクセスしてみようと思います。

少し長くなってきたので、次の記事に続きます。

※ DB側の設定はもう一つあって、Ruby からアクセスする際、ユーザー認証の「認証プラグイン」についての設定を変更する必要があります。そちらは続きの記事で。

【Ruby】require と require_relative

前置き

requirerequire_relative の違いと注意点についてです。

require

require は、引数で与えられたファイルパスのファイルを一度だけ呼び出します。このとき、引数のパスは、絶対パスでも相対パスでもOKで、相対パスの場合は、requireが呼ばれた時点でのカレントディレクトリからの相対パスになります。

C:\gyobo\test\ ディレクトリに、a.rbreq.rb の2つのファイルを置き、a.rb ファイルには、

require "req.rb"

とし、req.rb は、

p "required `req.rb`!"

と書いておきます。これで、カレントディレクトリを変えたりして a.rb を実行してみると、、、

C:\gyobo\test>ruby a.rb       # => "required `req.rb`!"

C:\gyobo>test\ruby a.rb       # => ruby: No such file or directory -- a.rb (LoadError)

カレントディレクトリが合っていないと、ファイルが見つからずに LoadError となってしまいます。

require_relative

require_relative も、引数で与えられたファイルパスのファイルを一度だけ呼び出しますが、相対パスが与えられた場合、実行しているファイルのある場所からの相対パスとして解釈してくれます。

先ほどと同じように、C:\gyobo\test\ ディレクトリに、a.rbreq.rb の2つのファイルを置いた状態で、a.rb ファイルの方を、

require_relative "req.rb"

に書きかえて、同じように実行してみると、、、

C:\gyobo\test>ruby a.rb       # => "required `req.rb`!"

C:\gyobo>test\ruby a.rb       # => "required `req.rb`!"

となり、実行するカレントディレクトリの場所に関係が無くなり、実行しているファイルの相対パスで呼び出せるようになります。

require_relative の注意点

require_relative では、__dir__と同様にシンボリックリンクを解決します。

例えば、C:\gyobo\test2\ ディレクトリに、sl_a という名前で C:\gyobo\test\a.rb へのシンボリックリンクを作成します。その状態で、sl_a を実行すると、、、

C:\gyobo\test2>ruby sl_a       # => "required `req.rb`!"

test2 ディレクトリにある sl_a ファイルを実行していますが、ちゃんと test\req.rb が呼び出されています。また、req.rbtest2 ディレクトリに移動させて実行すると、、、

C:\gyobo\test2>ruby sl_a
Traceback (most recent call last):
        1: from sl_a:1:in `<main>'
sl_a:1:in `require_relative': cannot load such file -- C:/gyobo/test/req.rb (LoadError)

実行しているのは sl_a ですが、C:/gyobo/test/req.rb を探しに行っているのが分かります。require_relativeは、あくまで実体ファイルのある場所からの相対パスで探索する、ということを忘れないように注意しましょう。

【Ruby】数値に3桁区切り文字をつける

前置き

Ruby で数値に3桁区切りを付加した文字列を取得する Tips です。

やり方

普通に考えると、

  1. 下桁から3桁ずつに区切って、
  2. 区切り文字を入れる。
  3. それを、桁がなくなるまで繰り返す。

という手順になりますが、Ruby だと一行でできます。(他の言語でもできるんだとおもいますが)

例えば、数値1234567 に区切り文字(仮にカンマ)を付与した文字列を取得する場合、

1234567.to_s.reverse.scan(/.{1,3}/).join(",").reverse      # => "1,234,567"

何をやっているかというと、

  • まず、to_s で文字列に変換 => "1234567"
  • 順序を反転する => "7654321"
  • scan メソッドで、正規表現にマッチした部分を繰り返して配列を取得。ここでの正規表現は「なんでもいいから少なくとも1文字、多くて3文字」にマッチする => { "765", "432", "1" }
  • join メソッドで、指定した文字列を区切りにして配列を結合 => "765,432,1"
  • 順序を反転する => "1,234,567"

となります。メソッドチェーンでつなげば、一行で書くことができます。

メソッド化

メソッド化するなら、区切り文字も引数で変えられるようにして、以下のような感じにしておけば良いように思います。メソッド名はお好みで。

def add_separaor(str, separator = ",")
    return str.to_s.reverse.scan(/.{1,3}/).join(separator.to_s).reverse
end

Rails 環境なら

Rails 環境なら、number_to_currency メソッドという便利なメソッドが用意されています。区切り文字だけでなく、単位やマイナスの場合の表現も変えられたり、多言語化もできるので、素直にこちらを使った方が良いです。

詳しい説明はこちらの記事を見てください。

https://qiita.com/azusanakano/items/c2e73521d5a4bdfa73d6

【Ruby2.6】__FILE__ を使ってできること

前置き

前回の続きです。 __FILE__ を使って色々な情報を取得してみます。

実行している「ファイル名のみ」を取得する

最後のパス区切り文字以降がファイル名になるので、それを取り出すメソッドを使う、正規表現で抽出したり、文字列加工したりすることで取得することができます。

下記、取り出し例です。C:\gyobo\test\a.rb 内で実行すると全て、"a.rb"文字列を返します。__FILE__の中身が絶対パスか、相対パスかにかかわらず、同じ結果が返ります。

# File.basename を使う。
File.basename(__FILE__)            

# "/" で配列に分割後、配列要素の最後のものを取る。
__FILE__.split("/")[-1]

# 最後の"/"から最後までを抽出。先頭に"/" が残るので、それを削除する。 
# "/" が無い場合は、そのままの値を返す。
__FILE__.include?("/") ? __FILE__.match(/\/[^\/]*$/).to_s.delete("/") : __FILE__

素直に File.basename を使うのが一番良いと思います。何かの理由でFileオブジェクトが使えない場合は、split を使うのが次善策でしょうか。

実行しているファイルの絶対パスを取得する

前回の記事でも書きましたが、__FILE__相対パスが入る場合、相対パスのベースとなるディレクトリの情報は入っていません。ですので、カレントディレクトリの情報と合わせる必要があります。

絶対パスを自力で生成しようとする場合、Dir.pwd 等でカレントディレクトリを取得し、join で結合することになりますが、__FILE__絶対パスかどうかの確認が必要になり、また__FILE__ の中に、親ディレクト.. やカレントディレクト. 等が入っている場合、ちゃんと処理をしないとそのまま入ってきてしまいます。

File.expand_path を使えば、第一引数が絶対パスであれば、第二引数を指定しなければ、カレントディレクトリを基準に絶対パスへの展開を行ってくれます。また、... の処理も合わせて行ってくれるので、素直に File.expand_path を使った方が良いです。

下記、そのまんまですが、取り出し例です。ファイルの絶対パスは、C:\gyobo\test\a.rb です。

File.expand_path(__FILE__)      # => "C:\gyobo\test\a.rb"

注意点ですが、絶対パスを取得する場合は、取得前にカレントディレクトリの変更(Dir.chdirなど)をしてしまうと、正しく取得できません。

p __FILE__                      # => "a.rb"
File.expand_path(__FILE__)      # => "C:\gyobo\test\a.rb"
Dir.chdir("C:\\")
File.expand_path(__FILE__)      # => "C:\a.rb"      移動したカレントディレクトリからのパスを生成してしまう。

実行しているファイルがあるディレクトリを取得する。

実行しているファイルの絶対パスを取得した後、絶対パスディレクトリ部分を取得すればいいです。ですが、File.expand_pathだけを使う方法もあります。

# ファイルの絶対パスからディレクトリを取得する。
File.dirname(File.expand_path(__FILE__))      # => "C:\gyobo\test"

# File.expand_path だけを使っても取れる。第一引数だけ注意。
p File.expand_path("..", __FILE__)         # => "C:\gyobo\test"

File.expand_path の方は、なんで第一引数が親ディレクト..指定なのか?これは、File.expand_path の特性を利用しています。

File.expand_path メソッドは、「第一引数のパスを、第二引数のパスを基準にして絶対パスに展開」します。第二引数も相対パスの場合、カレントディレクトリを基準にして、第二引数、第一引数のパスを絶対パスに展開してくれます。

  • 第二引数に__FILE__を指定した場合、まず第二引数がカレントディレクトリを基準にして展開され、C:\gyobo\test\a.rb となります。
  • ですが、第二引数にはディレクトリが来ることが想定されているので、このパスは C:\gyobo\test\a.rb\ 、つまりa.rbはファイルではなくディレクトリである、と解釈されます。
  • ですので、a.rbディレクトリを基準にして一つ上のディレクトリが、ファイルのあるディレクトリとなるので、第一引数が親ディレクト..の指定となります。

この特性を利用すると、実行しているファイルと同じディレクトリにあるlibディレクトリのパスを取得したい場合は、下記のようになります。

# 実行ファイルと同じディレクトリにある"lib"ディレクトリの絶対パスを取得する。
p File.expand_path("..\lib", __FILE__)         # => "C:\gyobo\test\lib"

便利なのですが、見た目上、一階層ずれるので、一瞬間違っているように見えることが注意点です。また、カレントディレクトリを基準にして取得するので、前項と同様に、取得前にカレントディレクトリの変更(Dir.chdirなど)をしてしまうと、正しく取得できなくなります。

もう一つの方法として、__dir__ メソッドでも取得することができます。(ruby 2.0 以上?)

p __dir__           # => "C:\gyobo\test\"

こちらは、カレントディレクトリの変更をしても、元のディレクトリが正しく取得できるので、バージョンに問題がなければ、こちらを使う方がおすすめだと思います。

ただ、こちらも注意点があり、リファレンスマニュアルの__dir__ の項目 にもある通り、シンボリックリンクを解決」したパスを返してきます。ですので、パスの中にシンボリックリンクが含まれている場合、File.expand_path__dir__ の結果が違ってきます。

例えば、実体ファイルが C:\gyobo\test\a.rb で、C:\gyobo\test2\link_testC:\gyobo\test へのシンボリックリンクとして作成して、C:\gyobo\test2\link_test\ をカレントディレクトリにして、a.rb を実行します。

p File.expand_path("..", __FILE__)       # => "C:\gyobo\test2\link_test"
p __dir__                                # => "C:\gyobo\test"

これは、実行ファイルa.rb自体をシンボリックリンクにした場合も同様です。

Windows環境の場合は、そもそもシンボリックリンクを作ること自体がけっこう特殊な状況なので、問題はより起きにくいと思いますが、linux系で、シンボリックリンク生成をする可能性がある場合は、要注意です。

まとめ

  • 実行している「ファイル名のみ」を取得する
    • File.basename(__FILE__)
  • 実行しているファイルの絶対パスを取得する
    • File.expand_path(__FILE__)
  • 実行しているファイルのあるディレクトリの絶対パスを取得する
    • File.expand_path("..", __FILE__)
    • __dir__

注意点としては、2点です。

【Ruby2.6】__FILE__ について考える。

前置き

Ruby の擬似変数__FILE__について、色々考えます。

そもそも、__FILE__ って何?

__FILE__は、「擬似変数」と呼ばれるものの一種です。Webで公開されているリファレンスマニュアルによると・・・

__FILE__
現在のソースファイル名
フルパスとは限らないため、フルパスが必要な場合は File.expand_path(__FILE__) とする必要があります。

となっています。実際、コード上で p __FILE__ で出力してみると、ファイル名のみだったり、フルパスだったり、中途半端に相対パスだったりと、さまざまな値が返ってきます。。。

Windows 環境のRubyで、以下のように確認してみました。

テスト用のファイル「C:\gyobo\test\a.rb」を作ります。内容は以下の一文のみ。

p __FILE__

これを、色々な方法で実行してみました。

C:\gyobo\test> ruby a.rb                # => "a.rb"
C:\gyobo> ruby test\a.rb                # => "test\a.rb"
C:\gyobo> ruby C:\gyobo\test\a.rb       # => "C:\gyobo\test\a.rb"
C:\gyobo> ruby c:\gyobo\test\a.rb       # => "c:\gyobo\test\a.rb"       あれ?
C:\gyobo> ruby ../gyobo\test\..\test\a.rb     # => "../gyobo/test/../test/a.rb"     そういうこと?

4行目、たまたまドライブ文字を小文字にしてみたら、__FILE__ の中身も小文字になったので、まさか・・・と思って5行目でやんちゃなことをしてみたのですが、、、

結局のところ、ruby コマンドで渡された実行ファイルへのパス、引数に指定したパスの文字列がそのまんま、__FILE__ に入るということのようです。

requireload で呼び出した場合

Ruby を実行開始したファイルではなく、requireload で呼び出した先では、__FILE__ の値はどうなるか? 先ほどの「a.rb」と同じディレクトリに、「req.rb」というファイルを作り、下の一行だけ書きます。

require './a.rb'

実行すると・・・

C:\gyobo\test>ruby req.rb
"C:/gyobo/test/a.rb"

相対パスで指定していますが、__FILE__ には絶対パスが格納されています。これは、require だけでなく、require_relativeload で読み込んでも同じです。また、カレントディレクトリを変更して実行した場合も同様*1require で指定する相対パスで探索し、見つかったらその絶対パスが入ってくるようです。

__FILE__ で得られるもの

まとめると、以下の通りのようです。

  • __FILE__ には、そのファイルを呼び出した際のパス文字列が格納される。
    1. ruby [ファイル名] で呼び出した場合は、「カレントディレクトリからの相対パス」文字列が格納される。
    2. require 等で呼び出した場合は、「絶対パス」文字列が格納される。

ポイントは、「文字列」である、ということです。

__FILE__.class         # => String

ファイル/ディレクトリオブジェクトではないので、格納されている文字列以上の情報は入っていません。上記1 の場合、__FILE__ の中身は相対パスの文字列でしかないので、__FILE__ だけでは、絶対パスを生成することはできません。ですので、絶対パスを取得する場合は、最初の引用の中にある通り、

フルパスとは限らないため、フルパスが必要な場合は File.expand_path(__FILE__) とする必要があります。

カレントディレクトリを基準に、絶対パスに展開できる File.expand_path 等を使って生成する必要があるわけです。

続きます。

*1:カレントディレクトリに合わせて、require で指定するパスを変更する必要があります

【ツール作成】メインの流れ

前置き

最初に実行するメインフローの部分です。他の部分はできているので、順にメソッドを呼び出すだけになっています。

実装コード

最初に、必要なモジュール、クラスをrequireで読み込みます。

唯一、system.iniファイルだけは、固定でパスを与えています。(実行ファイルと同じ場所に置きます。)

後は、流れにしたがって、メソッドを呼んでいくだけになっています。

require './modules/Message'
require './modules/Setting'
require './modules/Utility'
require './modules/ProgressBar'

SYSTEM_INI = "./system.ini".freeze

# システム設定読み込み
sys = SystemSetting.new(SYSTEM_INI)

# メッセージクラスの初期設定
Message.init(sys) 

# ディレクトリ情報の取得
dirs = DirectorySetting.new(sys.setting_path)

# 情報表示と実行確認
BackupUtils.show_dir_info(dirs)
BackupUtils.show_confirmation

# バックアップ実行
BackupUtils.execute_copy(dirs)