[Ruby] FTPSを使ってみた



Nプログラマ(@Nprog128)です。

さくらのブログで、外部読み込みするcssファイルをFTPクライアントツールを使ってアップロードしていたのですが、マウス操作が面倒だったので勉強も兼ねてFTPSを使ったプログラムを作ってみました。

なプ

FTPクライアントツールの同期機能を使えば?という言葉は聞こえませんw

概要

ローカルにある指定したディレクトリ配下にあるファイルを、対象のサーバの指定したところにアップロードするものです。

シンプルな機能なので、ライブラリのお力でなんとかなりそうです。

入れ子には未対応

ディレクトリの入れ子には対応していません。
ディレクトリ直下にあるファイルのみをサーバにアップロードします。

ソースコード

こちらが作ったもの。

コード コードを開く
コード
 1require 'net/ftp'
 2
 3debug_mode = false
 4if (ARGV.size() > 0) then
 5  debug_mode  = (ARGV[0] == "-d") ? true : false
 6end
 7
 8ftp_url     = ENV['FTP_URL']
 9user_name   = ENV['FTP_USER_NAME']
10user_pass   = ENV['FTP_USER_PASS']
11upload_path = ENV['FTP_UPLOAD_PATH']  // アップロード先のディレクトリのパス
12
13local_files = []
14for ext in ['*.js', '*.css']
15    for file in Dir.glob(Dir.pwd + '/resources/' + ext) do
16      local_files.push(file)
17    end
18end
19
20begin
21    ftps = Net::FTP.new(
22        ftp_url,
23        ssl: true,
24        username: user_name,
25        password: user_pass,
26        debug_mode: debug_mode,
27    );
28    ftps.chdir(ftps.getdir + upload_path + File.basename(Dir.pwd))
29    for local_file in local_files do
30      ftps.put(
31          local_file,
32          ftps.getdir + '/' + File.basename(local_file)
33      )
34      puts 'upload local file: ' + local_file
35      puts 'upload server file: ' + ftps.getdir + '/' + File.basename(local_file)
36    end
37rescue => e
38    ftps.quit
39    puts "エラー"
40    p e
41end
42
43ftps.quit
44

説明

ざっくりとした流れはこんな感じです。

  1. 環境変数から必要な情報を取得
  2. アップロード対象のファイルを追加
  3. アップロード

各項目を説明していきます。

1. 環境変数から必要な情報を取得

コード コードを開く
コード
1
2ftp_url     = ENV['FTP_URL']
3user_name   = ENV['FTP_USER_NAME']
4user_pass   = ENV['FTP_USER_PASS']
5upload_path = ENV['FTP_UPLOAD_PATH']  // アップロード先ディレクトリのパス
6

作成したコードはgitで管理する予定だったので、アカウント情報の直接記述は避けたいところでした。
なので、入力は環境変数から取得する作りになっています。

この部分はケースバイケースで変更すればいいかなと思っています。 自分は毎回の手入力を避けたかったため、このような形にしました。

オプションで変更できるようにしてみるのもいいかもしれないですね。
デバッグ用オプションは実装してあるので、これをちょっと応用すればできそうです。

2. アップロード対象のファイルを追加

コード コードを開く
コード
1local_files = []
2for ext in ['*.js', '*.css']
3    for file in Dir.glob(Dir.pwd + '/resources/' + ext) do
4      local_files.push(file)
5    end
6end

ここではローカルのプログラムと同じ場所にあるresourcesディレクトリの下にあるjscssのファイルパスを取得して、ファイルアップロードするファイルリスト変数local_filesに入れています。

3. アップロード

コード コードを開く
コード
 1begin
 2    ftps = Net::FTP.new(
 3        ftp_url,
 4        ssl: true,
 5        username: user_name,
 6        password: user_pass,
 7        debug_mode: debug_mode,
 8    );
 9    ftps.chdir(ftps.getdir + upload_path + File.basename(Dir.pwd))
10    for local_file in local_files do
11      ftps.put(
12          local_file,
13          ftps.getdir + '/' + File.basename(local_file)
14      )
15      puts 'upload local file: ' + local_file
16      puts 'upload server file: ' + ftps.getdir + '/' + File.basename(local_file)
17    end
18rescue => e
19    ftps.quit
20    puts "エラー"
21    p e
22end

まずは取得した認証情報を使って、FTPSで接続します。

サーバのアップロードするディレクトリ先をchdir関数でセットします。
その後は、アップロード先ディレクトリとアップロードするファイル名を結合して、フルパス指定でファイルをアップロードします。

アップロード完了後、確認のためにアップロードしたローカルファイルと、アップロード先のファイルをフルパスで表示しています。

例外処理では、エラーが起きたらFTPを切断するようにしました。

sslオプションについて

rubyのFTPのsslオプションは2.4.0から入ったそうです。
詳しくは、最後の参考リンクもご確認ください。

考察

プログラム実行するたびに接続、アップロード、切断という処理が走るのでサーバにはちょっと優しくないかも。

FTPの接続を維持しつつコマンドを受け付けるようにして、アップロード、切断のコマンドを作ればより使いやすいかなと思いました。

感想

ライブラリをお力を借りて簡単に実装することができました。なぜrubyを選んだのかは、なんとなく読みやすかったからです。

これ、複数の接続を張ったままサーバ側が溢れたどうなるのだろう。。。時間ある時に調べてみたいと思います。こういう内部のことも分かってくると、初心者卒業なんだろうなーと思っています。がんばります。

なぜRubyを選んだか?

単純にshellが苦手で書きたくなかった、というだけです(笑)

何度かshellを覚えようとしたのですが、なぜか文法が全然頭に入らなかったのでshellは自分には合わないのだろうと思って諦めています。

どうしても必要な時は書きますが、なるべくなら避けたい。。。

まとめ

rubyでFTPSを使って、ローカルファイルをサーバにアップロードする内容でした。

状況に合わせてカスタマイズして使ってみてください。

それでは、このへんで。
バイナリー!

\ ちょっとお買い物 /