[Ruby] FTPSを使ってみた



Nプログラマです。

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

なプ

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

概要

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

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

入れ子には未対応

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

ソースコード

こちらが作ったもの。

コード コードを開く
コード

require 'net/ftp'

debug_mode = false
if (ARGV.size() > 0) then
  debug_mode  = (ARGV[0] == "-d") ? true : false
end

ftp_url     = ENV['FTP_URL']
user_name   = ENV['FTP_USER_NAME']
user_pass   = ENV['FTP_USER_PASS']
upload_path = ENV['FTP_UPLOAD_PATH']  // アップロード先のディレクトリのパス

local_files = []
for ext in ['*.js', '*.css']
    for file in Dir.glob(Dir.pwd + '/resources/' + ext) do
      local_files.push(file)
    end
end

begin
    ftps = Net::FTP.new(
        ftp_url,
        ssl: true,
        username: user_name,
        password: user_pass,
        debug_mode: debug_mode,
    );
    ftps.chdir(ftps.getdir + upload_path + File.basename(Dir.pwd))
    for local_file in local_files do
      ftps.put(
          local_file,
          ftps.getdir + '/' + File.basename(local_file)
      )
      puts 'upload local file: ' + local_file
      puts 'upload server file: ' + ftps.getdir + '/' + File.basename(local_file)
    end
rescue => e
    ftps.quit
    puts "エラー"
    p e
end

ftps.quit

説明

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

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

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

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

コード コードを開く
コード

ftp_url     = ENV['FTP_URL']
user_name   = ENV['FTP_USER_NAME']
user_pass   = ENV['FTP_USER_PASS']
upload_path = ENV['FTP_UPLOAD_PATH']  // アップロード先ディレクトリのパス

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

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

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

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

コード コードを開く
コード

local_files = []
for ext in ['*.js', '*.css']
    for file in Dir.glob(Dir.pwd + '/resources/' + ext) do
      local_files.push(file)
    end
end

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

3. アップロード

コード コードを開く
コード

begin
    ftps = Net::FTP.new(
        ftp_url,
        ssl: true,
        username: user_name,
        password: user_pass,
        debug_mode: debug_mode,
    );
    ftps.chdir(ftps.getdir + upload_path + File.basename(Dir.pwd))
    for local_file in local_files do
      ftps.put(
          local_file,
          ftps.getdir + '/' + File.basename(local_file)
      )
      puts 'upload local file: ' + local_file
      puts 'upload server file: ' + ftps.getdir + '/' + File.basename(local_file)
    end
rescue => e
    ftps.quit
    puts "エラー"
    p e
end

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

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

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

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

sslオプションについて

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

考察

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

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

感想

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

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

なぜRubyを選んだか?

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

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

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

まとめ

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

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

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