環境
- Ruby 2.6.3
- Rails 5.2.3
- net-sftp 2.1.2
前提
net-sftpとは、RubyでSSHプロトコルを使用し、暗号化を行なってファイルの送受信を行うことが出来るライブラリです。
ユースケースとしては外部システムと連携するときなどにアプリケーションのデータをファイル化して、外部サーバーに配置したりするとかだと思います。
https://github.com/net-ssh/net-sftp
Gemfile
に以下を記述して、 bundle install
すれば使えるようになります。
gem 'net-sftp'
具体的な
net-sftp
の使用方法は検索をすると結構出てくるので、割愛させていただきます。
起きた問題
putsを使って外部サーバーへファイルを保存する際大容量の書き込みがいつまで経っても終わらない問題に遭遇した。
以下が該当のコード
csv_str = 'hogehogeho,hogehoge,hogehoge' # csvフォーマットにした文字列が入っている
path = '/var/www' # 出力先のファイルパス
filename = 'hoge.csv' # 出力したいファイル名
Net::SFTP.start('host', 'user', :password => 'password') do |sftp|
sftp.file.open("#{path}/#{filename}", 'w') do |f|
f.puts csv_str
end
end
ログを見た所、ロジックとしてはエラーとならずに f.puts csv_str
で処理が止まって動かなくなっていた。
対応方法
ファイルを直接サーバーに書き込むのはやめ、一度 tmp
ディレクトリなどにファイルを配置してから、 upload!
メソッドを使ってファイルのアップロードをすることで解決した。
具体的にどのくらいの容量から
puts
が動作しなくなるのかの計測が出来なかったので、基本的にはファイルのアップロードはputs
ではなく、upload!
メソッドを使用するのがいいと思う
以下が具体的なコード
csv_str = 'hogehogeho,hogehoge,hogehoge' # csvフォーマットにした文字列が入っている
path = '/var/www' # 出力先のファイルパス
filename = 'hoge.csv' # 出力したいファイル名
tmp_dir = "#{Rails.root.to_s}/tmp"
# 一度tmpディレクトリへputsでファイルを生成する
File.open("#{tmp_dir}/#{filename}", "w") do |file|
file.puts csv_str
end
# tmpディレクトリに作成したファイルをuploadする
Net::SFTP.start('host', 'user', :password => 'password') do |sftp|
sftp.upload!("#{tmp_dir}/#{filename}", "#{path}/#{filename}")
end
net-sftpを使用する際は上記を気をつけて実装してみてください。