酒と泪とRubyとRailsと

Ruby on Rails と Objective-C は酒の肴です!

Net::SSH、Net::SCP RubyでSSH/SCPコマンドを実行 [Ruby]

RubyからSSHコマンドやSCPコマンドを簡単に実行できるGem『Net::SSH』と『Net::SCP』の紹介です。

今までsystemで直接実行していましたが、サーバを最近乗り換えたら、パスワード、鍵認証、鍵のパスフレーズなどではまってしまいましたので、このGemにはすごく助かりました!


Gemのインストール

Gemfileに以下を追加して、コンソールでbundleを実行してください。

1
2
3
# SSH/SCPコマンドのサポート
gem "net-ssh"
gem "net-scp" # scpコマンドを使わない場合は不要

SSHコマンドの使い方

公開鍵認証を使って、SSHコマンドを実行する場合は次のようなコードになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
require 'rubygems'
require 'net/ssh'

opt = {
    :keys => '公開鍵のパス',
    :passphrase => '公開鍵のパスフレーズ',
    :port => # SSHのポート番号
}

# コネクションを確立
Net::SSH.start('ホスト名', 'ユーザー名', opt) do |ssh|
    # コマンドを実行
    ssh.exec!('do something')
end

標準出力/標準エラー出力を取得する

標準出力/標準エラー出力を取得したい場合はこちら。

1
2
3
4
5
6
7
8
9
10
stdout = ""
stderr = ""

ssh.exec!("ls -l /home/jamis") do |channel, stream, data|
  stdout << data if stream == :stdout
  stdrrr << data if stream == :stderr
end

puts stdout
puts stderr

標準入力への値のセット

パスワードを標準入力に値をセットしたい場合はこちら。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
# 新しいチャンネルを開く
ssh.exec! "do something" do |channel, success|
  raise "コマンドを実行出来ません" unless success

  channel.on_data do |c, data|
    # パスワードを要求された場合
    if data =~ /password/ then
      channel.send_data "パスワード\n"
    end
    puts data
  end
end

ssh.loop { true }

ポートフォーワーディング

ポートフォーワーディングを設定したい場合はこちらの記述を追加。

1
2
3
4
Net::SSH.start('host', 'user', :password => "password") do |ssh|
  # ポートフォーワーディング : ローカル ポート1234 => サーバ capify.org の ポート80
  ssh.forward.local(1234, "www.capify.org", 80)
end

ポートフォーファーディングも壮絶簡単に出来ますね!

SCPコマンドの使い方

公開鍵認証を使って、SSHコマンドを実行する場合は次のようなコードになります。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
require 'rubygems'
require 'net/ssh'
require 'net/scp'

opt = {
    :keys => '公開鍵のパス',
    :passphrase => '公開鍵のパスフレーズ',
    :port => # SSHのポート番号
}

Net::SSH.start('ホスト名', 'ユーザー名', opt) do |ssh|
    # アップロードする場合 local => remote
    ssh.scp.upload! "/local/path", "/remote/path"

    # ダウンロードする場合 local => remote
    ssh.scp.download! "/local/path", "/remote/path"

    # メモリのデータをアップロードする場合
    scp.upload! StringIO.new("some data to upload"), "/remote/path"

  # 複数ファイルを並行してダウンロードする場合 
  d1 = scp.download("/remote/path", "/local/path")
  d2 = scp.download("/remote/path2", "/local/path2")
  [d1, d2].each { |d| d.wait }
end

このように簡潔にSSHコマンドを書くことができます。もし、SSH/SCPコマンドを使いたいときにはぜひ、お試し下さい!

公式サイト

Net::SSHの公式サイトはこちら。

net-ssh/net-ssh · GitHub

Net::SCPの公式サイトはこちら。

net-ssh/net-scp · GitHub

Special Thanks

Pure Ruby な SSH クライアントライブラリ「Net::SSH」 - WebOS Goodies

RubyのNet::SSHの使い方.リモートサーバー内でsuしたりrsyncするrubyスクリプトが作れるようになる - それマグで!

ssh - Ruby NET::SCP and custom ports - Stack Overflow

おすすめの書籍