それマグで!

知識はカップより、マグでゆっくり頂きます。 takuya_1stのブログ

習慣に早くから配慮した者は、 おそらく人生の実りも大きい。

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

SSHのコマンドをRubyから実行出来たら便利ですよね。シェルスクリプトとExpectでも良いんですが.Rubyパッケージを利用するともっと書きやすくなりますよね.

Net::SSHパッケージ

net-ssh は version 1.x と2.xがあって2.xの方がわかりにくい.普通にインストールすると2.xが入るので2.xを前提にする。

インストール

gem install net-ssh

基本的な使い方

リモートサーバー内にアクセスする.

require 'rubygems'
require 'net/ssh'
 
Net::SSH.start('hostname', 'user', :password => 'password') do |ssh|
  puts ssh.exec! 'ls /etc/'
end

公開鍵・秘密鍵を使ってログインする

Net::SSH.start('hostname', 'username', :keys => ['/path/to/private_key'], :passphrase => 'passphrase') do |ssh|
end

ここまでは簡単なんですよ.チョッと突っ込んだ使い方をすると途端に難しくなる.

対話入力があると全滅

  • su する
  • sudo する
  • rsync をする(対話的パスワード認証)

こうのはどうするか?

対話的なコンソールをNet::SSHから使って自動化する

対話コンソールに入力を流し込みたい。その為に、出入力のttyを確保する。
その為に request_pty っていうメソッドがある。

      channel.request_pty do |ch, success| end

コレを使って,対話的なIntractiveShellを使うことが出来るみたい

channelってなに

net-ssh のサブクラスです。ssh の接続は複数のデータチャネルをもてるみたいです。
Channel単位で出入力を制御している。つまり対話コンソールに入力するのも出力を受信するのもChannel経由で行うようです.(よくわかってない)

ゲートウェイを踏み台にRsyncを起動するRuby

仕組みを調べるとSSHそのものに対する理解が必要なので詳しくはパスするとして.

手元のターミナルでRubyを起動して,Rubyがゲートウェイに接続し,ゲートウェイでRsyncを起動させてみる。

Terminal->Ruby->Net::SSH---->Gateway->SSH(rsync)---->Server

のような接続をする。手作業でしていた同期処理を自動化してみる。

#!/usr/bin/env ruby
require 'rubygems'
require 'net/ssh'

Net::SSH.start('gw.example.net', 'USERNAME', :password => '****') do |ssh|
    command = "rsync -avz --progress /var/www/ 192.168.10.21:/var/www/\n"
    channel = ssh.open_channel do |ch|
      channel.request_pty do |ch, success|
        raise "Could not obtain pty " if !success
      end
      channel.exec command do |ch, success|
        raise "failed to execute command" unless success
        ch.on_data do |c, data|
          if data =~ /password/ then #入力ダイアログが来たら
            channel.send_data "****\n" #パスワードを送信する
          end
          puts data
        end
      end
    end
    ssh.loop#転送待ち
end

一回動いてしまえば簡単でした.

関連

Expect コマンドで同じことをする
コマンドを自動化する expect - ブックマクロ開発に