ローカルネットワーク内に何台か PC があるので、Ruby でファイル転送を行うことを考えました。SSH でやってもよいのですが、一台の PC に Linux をマルチブートしているので、面倒なので Ruby でやります。セキュリティは何も考えていないので、当り前ですが絶対にインターネットに出てはいけません。というか、ローカルでも可能な限り SSH(scp コマンド)でやった方がいいと思います(参考)。
使い方はこんな感じ。受け手側(もちろんこちらを先に実行して下さい)。
$ file_transfer trans IPアドレス: 192.168.11.6 [192.168.11.2:34098] からの接続を了承しました spline_curve.png を受信中です... spline_curve.png の受信が完了しました
送り手側。
$ file_transfer trans 192.168.11.6 spline_curve.png spline_curve.png を送信中です... spline_curve.png の送信が完了しました
コードはこんな感じです。基本的にここのコードを流用させて頂きました(ありがとうございます!)。
file_transfer
#!/usr/bin/env ruby require 'socket' require 'thor' class FileTransfer < Thor desc 'trans', "Transfer a file." def trans(*args) send_file = lambda do |host, name| puts "#{name} を送信中です..." open(name, "rb") do |file| size = File.size(name) sock = TCPSocket.open(host, 7413) sock.puts "PUT_FILE #{name} #{size}" sock.write(file.read) sock.close end puts "#{name} の送信が完了しました" end receive_file = lambda do print "IPアドレス: " ip_ad = Socket.getifaddrs.select {|x| x.addr.ipv4?} puts ip_ad.select {|x| x.addr.ip_address.include?("192.168")}[0].addr.ip_address s0 = TCPServer.open(7413) loop do Thread.start(s0.accept) do |sock| puts "[#{sock.peeraddr[3]}:#{sock.peeraddr[1]}] からの接続を了承しました" while (m = /^PUT_FILE\s+(\S+)\s+(\d+)$/.match(sock.gets.chop)) name, size = File.basename(m[1]), m[2] puts "#{name} を受信中です..." open("#{name}", "wb") do |file| file.write(sock.read(size.to_i)) end puts "#{name} の受信が完了しました" end puts "[#{sock.peeraddr[3]}:#{sock.peeraddr[1]}] からの接続が拒否されました" sock.close end end end host, file_name = args if file_name send_file.call(host, file_name) else receive_file.call end end end FileTransfer.start
コマンド化は Gem 'thor' で行っているので、これをインストールする必要があります。そして、ファイルに実行権を与えて、/usr/local/bin などにコピーして下さい。なお、ポート番号など細かいところは適宜各自の環境に合わせて下さい。
なお、rbenv を利用して Ruby をインストールされている方は、シェバング行を
#!/home/***/.rbenv/versions/2.3.3/bin/ruby
のように変更して下さい。もちろん「***」や Ruby のバージョンの部分は適宜自分の環境に合わせて下さい。
※参考
お手軽ファイル転送 - Usipedia
Ruby 2.1.0 では Socket.getifaddrs で簡単にインターフェイスのアドレスを取れる
Ruby の Thor でコマンドを作る - Marginalia
※追記
このままだとバイナリファイルや(ネストした)ディレクトリが送れなかったりするので、改良版を作りました。
obelisk.hatenablog.com