おけらのブログ++

駆け出しWebエンジニアの奮闘記

Rubyでsambal を使ってデータを取得する

仕事でsambaにアクセスして自動でデータを取ってくるツールを作ることがあったので、その記録をしていきます。

以下サイトが大変参考になりました。
Ruby から Windows の共有フォルダにアクセスする - akishin999の日記

sambalライブラリ

今回はRubyでsambalというライブラリを使って実現しました。そもそもsambaアクセスがどのように出来るかは以下のサイトがわかりやすいです。
実践初級ITブログ LinuxからWindowsの共有ドライブにアクセス(smbclientコマンド)

samba-clientのインストール

sambalはsamba-clientをラッパーしているようなのでまずはsamba-clientをインストールします。

yum install -y samba-client

sambalのインストール

Gemでsambalのインストールを行います。

bundle init

Gemfileが生成されるのでgem 'sambal'と記載してbundle installします。
これにて事前準備完了です。



sambalのコマンド

sambalのコマンドについては下記で公開されています。今回使用したものについて説明します。
GitHub - akishin/sambal: Ruby Samba Client

Sambal::Client.new: インスタンスの生成

client = Sambal::Client.new(host:  host,
                            share:  dir,
                            user:   user,
                            password: pass)

まず何をするにしてもこれが必要になります。これでclientオブジェクトを生成することで下記のコマンドが使えるようになります。

client.ls : ディレクトリのファイル一覧を取得
puts client.ls

このコマンドの戻り値から以下のような情報が取得できます。

  • type => ファイル or ディレクト
  • size => ファイルサイズ
  • modified => 更新日
puts client.ls
{
"data"=>{ 
:type=>:directory, 
:size=>"0", 
:modified=>2018-06-25 14:26:53 +0900}, 

"test.zip"=>{
:type=>:file, 
:size=>"7331462", 
:modified=>2018-06-25 14:17:24 +0900}, 

"IMG_0217.mp4"=>{
:type=>:file, 
:size=>"2042582", 
:modified=>2018-06-25 11:51:09 +0900}, 
}

データの取り出し方サンプル

info = client.ls
info.each do |key, data|
  if((data[:type].to_s == "file") && (data[:size] != 0)) then
    #ファイルを取得
    client.get(key.to_s,  "hoge.mp4")
  end
end

keyには例でいうdataやtest.zip,IMG_0217.mp4が入ってきます。
そしてdataからハッシュで:typeや:size,:modifiedの中身を取り出すことができます。

client.get: sambaからデータを取得する

実際にsambaからデータを取得する際に使うコマンドです。第一引数にはそのファイル名(path)をいれ、第二引数には取得後のファイル名をいれます。

client.get("remote_file.*", "local_file.*")

ここで注意しなければならないのは、あくまでダウンロードできるのはファイルだけということです。
いろいろと調べたのですが、おそらくフォルダごとダウンロードすることはできなさそうです。そのためフォルダごとダウンロードしたい場合は、自分で再帰処理を作ってダウンロードしなければなりません。

client.cd: ディレクトリ位置を変える

これもUNIX系のcdコマンドと同じ感覚で使用できます。現在のディレクトリから変更したいディレクトリ名をいれて変更します。

client.close :終了処理

これもお作法で最後にcloseしてインスタンスを破棄します。


sambalを使ってデータを取ってくる

ここからが本題のデータ取得方法についてです。今回は下記のようなディレクトリ構成になっている想定でやっていきます。
f:id:Okerra:20180624002410p:plain
例として、ファイル実行時に取ってきたいファイルの日付を入力するとそのフォルダの中のテキストファイルを取ってくるようにします。

ソースコードsample

# download_samba.rb
require 'yaml'
require 'date'

begin
  # config情報取得
  config = YAML.load_file("config.yml")
  host = config["user"]["host"]
  dir  = config["user"]["dir"]
  user = config["user"]["user_id"]
  pass = config["user"]["pass"]

  # SambaClient open
  client = Sambal::Client.new(host:     host,
                              share:    dir,
                              user:     user,
                              password: pass)
  
  puts " When will you get a data?(YYYYMMDD):"
  date = STDIN.gets.chomp

  # データ取得後のファイル格納フォルダをsystem関数を使って作成
  # 日付と日時から生成
  now = Time.now
  output_fld =  now.strftime('%Y%m%d_%H%M%S')
  system("mkdir " + output_fld)

  puts "******** Download Start ********"

  # download file
 ret = download_file(client, date, output_fld)

  puts "******** Download End ********"

  client.close
end
#----------------------------------------------
#        module : ダウンロード処理
# function name : download_file()
#         input : client => samba client object
#         input : date   => YYYYMMDD
#         input : wk_fld => work directory path
#----------------------------------------------
def download_file(client, date, wk_fld)

  # samba(data/YYYYMMDD)にあるファイル一覧を取得
  client.cd "data"
  client.cd date
  dir_info = client.ls

  # Download 
  dir_info.each do |key, data|
    if((data[:type].to_s == "file") && (data[:size] != 0)) then
      # ファイルを取得
      client.get(key.to_s, "./" + wk_fld.to_s + "/" + key.to_s)
    end
  end

  return
end

ruby初心者のため誤っていたり、もっと良い書き方があるかもしれません。
またブログ用に修正しており、このまま実行するとエラーが出るかもしれません。

configファイル
# download_samba.rb
require 'yaml'

begin
  # config情報取得
  config = YAML.load_file("config.yml")
  host = config["user"]["host"]
  dir  = config["user"]["dir"]
  user = config["user"]["user_id"]
  pass = config["user"]["pass"]
# config.yml
user:
  host: example.co.jp
  dir: data
  user_id: hoge
  pass: hogehoge

今回はチーム内に展開する想定だったためログインのためのconfig情報を外に出して、変更出来るようにしました。
Rubyでyaml形式の設定ファイルを用意して、値を取得する - Code Log

ポイント client.ls

やはりディレクトリ内のファイル情報の扱い方(client.ls)がポイントとなると思います。下記のようにファイル種別が"file"のみを取得して、フォルダ内のフォルダ以外のファイルをすべてダウンロードします。

  dir_info = client.ls

  # Download 
  dir_info.each do |key, data|
    if((data[:type].to_s == "file") && (data[:size] != 0)) then
      # ファイルを取得
      client.get(key.to_s, "./" + wk_fld.to_s + "/" + key.to_s)
    end
  end

最後の一言

今回はrubyによるsambalライブラリを使ってsambaにアクセスすることができました。
sambalに関する情報が意外と調べてもなかったので、今後使いたい人の手助けになれば幸いです。