Ruby から Windows の共有フォルダにアクセスする
Linux 上で Samba マウントせずに Windows の共有フォルダにアクセスしたかったので、Ruby の sambal というライブラリを使ってみました。
johnae/sambal
https://github.com/johnae/sambal
試した環境は以下です。
Ruby が 2.0 なのは単に手元で 2.1 の RPM をまだ作成していないだけです^^;
インストール
sambal は smbclient コマンドのラッパーなので、動作には smbclient コマンドが必要になります。
smbclient は yum から samba-client コマンドを実行するとインストールできます。
# yum install -y samba-client
インストールしたら Windows の共有フォルダにアクセスできるかを確認。
$ smbclient //PC001/Share "shakiyamain" -U akishin -p 445
smb: \> というプロンプトが表示されていれば接続は成功です。
ls と打つと共有フォルダ内のファイルを確認する事が出来ます。
プロンプトは exit で抜ける事ができます。
smb: \> ls . D 0 Tue Feb 18 22:43:37 2014 .. D 0 Tue Feb 18 22:43:37 2014 test.txt A 0 Tue Feb 18 22:43:36 2014 62499 blocks of size 16777216. 33957 blocks available smb: \> exit
ちなみに WORKGROUP ではなくドメインに参加している場合は以下のような感じ。
$ smbclient //PC001.example.co.jp/Share "p@ssword" -W example.co.jp -U akishin -p 445
これで sambal を使う準備は整いました。
ここでは bundler でインストールするので、まずは Gemfile を作成します。
$ bundle init
実行したディレクトリ内に Gemfile が生成されるので編集します。
$ vi Gemfile
本来なら配布されている gem を使えばいいので「gem 'sambal'」と書けばいいのですが、試したところ CentOS では以下のようなエラーになってしまい上手く動きません。
$ bundle exec ruby sambal_example.rb Failed to connect Unknown Process Failed!! (exit): "exit" /root/vendor/bundle/ruby/2.0.0/gems/sambal-0.1.2/lib/sambal.rb:70:in `exit' /root/vendor/bundle/ruby/2.0.0/gems/sambal-0.1.2/lib/sambal.rb:70:in `initialize' sambal_example.rb:9:in `new' sambal_example.rb:9:in `<main>'
どうも smbclient コマンドのプロンプト文字列をパースしている正規表現が若干異なるようです。
仕方ないので取りあえず Fork してエラーにならないように修正したものを使用しました。
https://github.com/akishin/sambal
上記を使う場合、 Gemfile には以下のように記述します。
gem 'sambal', github: "akishin/sambal"
bundle install 実行。
bundle install --path=vendor/bundle
これで sambal のインストールは完了です。
使ってみる
以下のような感じで接続して ls を実行してみます。
require 'sambal' begin HOST = 'PC001' DIR = 'Share' USER = 'akishin' PASS = 'p@ssword' client = Sambal::Client.new(host: HOST, share: DIR, user: USER, password: PASS) puts client.ls client.close rescue => e puts e end
ドメインに参加している Windows に接続する場合は以下のようにしてドメインを指定します。
require 'sambal' begin DOMAIN = 'example.co.jp' HOST = 'PC001.example.co.jp' DIR = 'Share' USER = 'akishin' PASS = 'p@ssword' client = Sambal::Client.new(domain: DOMAIN, host: HOST, share: DIR, user: USER, password: PASS) puts client.ls client.close rescue => e puts e end
実行すると以下のような結果が表示されました。
$ bundle exec ruby sambal_example.rb {"."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 22:43:37 +0900}, ".."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 22:43:37 +0900}, "test.txt"=>{:type=>:file, :size=>"0", :modified=>2014-02-18 22:43:36 +0900}}
ちゃんと共有フォルダの内容が読み取れているようです。
次は何かファイルを置いてみます。
Sambal::Client#put メソッドでローカルのファイルを共有フォルダに配置することができます。
require 'sambal' begin HOST = 'PC001' DIR = 'Share' USER = 'akishin' PASS = 'p@ssword' client = Sambal::Client.new(host: HOST, share: DIR, user: USER, password: PASS) client.put('/home/akishin/image.png', 'image.png') # <- 追記 puts client.ls client.close rescue => e puts e end
実行すると以下のように image.png が結果に含まれている事がわかります。
また、実際に共有フォルダを確認するとファイルが配置されていました。
$ bundle exec ruby sambal_example.rb {"."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 23:06:46 +0900}, ".."=>{:type=>:directory, :size=>"0", :modified=>2014-02-18 23:06:46 +0900}, "image.png"=>{:type=>:file, :size=>"29618", :modified=>2014-02-18 23:06:46 +0900}, "test.txt"=>{:type=>:file, :size=>"0", :modified=>2014-02-18 22:43:36 +0900}}
当然ですが Windows の共有フォルダに接続ユーザで書込み権限が必要なので、もし上手く行かない場合には確認してみて下さい。
というわけで、こんな感じでわざわざマウントしなくても Windows の共有フォルダに簡単にアクセスする事が出来ました。
Windows, Linux が混在しているような環境でスクリプトを書く際には結構重宝しそうです。