RubyからディレクトリごとサーバーにFTP転送する処理を書きたかったのですが、最初なかなかうまくいきませんでした。
Rubyのftpライブラリでエラー多発
RubyからFTPを使う場合net/ftpを使うのが一般的らしいです。また、これをラップしているdouble-bag-ftpsも試しました。
ですが、loginまでは正常にできるのですが、一覧取得やファイル転送をすると止まってしまったり、エラーが発生してしまいます。
例えば、以下のようなエラーです。
1 |
Errno::ECONNRESET: Connection reset by peer |
1 |
Net::FTPReplyError: 150 Opening ASCII mode data connection for file list |
1 |
200 Type set to I. (Net::FTPReplyError) |
かなりハマりましたが、結局Rubyのライブラリーではなく、外部コマンドを使って行うことで解決しました。
スポンサーリンク
lftpで解決
lftpというコマンドです。MacでHomebrewをお使いであれば、
1 |
brew install homebrew/boneyard/lftp |
でインストールできるはずです。
このコマンドはかなり安定感があり、今まで一度もエラーは発生していません。また、Rubyのnet/ftpなんかは仮に正常に動いたとしてもディレクトリ全体を転送することはできないので、1ファイルごとに転送する必要がありました。ですが、lftpはディレクトリを指定し、一括で転送することができます。
Rubyからの使い方としては、こんな感じのスクリプトにしておくと
1 2 3 |
command = "lftp -u #{id},#{pass} -e \'mirror -R --only-newer #{source} #{dest}; exit;\' #{host}" puts command puts `#{command}` |
こんな出力をしてくれて、きちんと転送してくれます。
1 2 3 4 5 |
lftp -u id,password -e 'mirror -R --only-newer source_dir dest_dir; exit;' host.jp Total: 3 directories, 161 files, 0 symlinks Modified: 161 files, 0 symlinks 704729 bytes transferred in 10 seconds (71.4 KiB/s) To be removed: 1 directory, 0 files, 0 symlinks |
いやー、でもなんでRubyのnet/ftpはいまいち動作がおかしいんだろうか。