中野智文

中野智文(VOYAGE GROUP)のコンピュータなどのメモ

複数のマシンで実行しパスワードを求められたら入力するスクリプト

2014-01-15 18:11:55 | ruby

背景

複数のマシンで同じコマンドを実行したい、そんなときに限り、sudoでパスワード聞かれ、面倒に。検索したところ、expectを使ったものが見付かった(参考:Rubyで exptect や ptyを使ってパスワードを自動入力する)。 かなりやりたいことと近かったが、expectで待ち構えるパターンが複数のときが分からなかったため、rubyのexpectのソースを参考に次のように 作成した。

コード

#!/usr/bin/ruby -Ku 

# 使用法: このコマンド マシンリストファイル コマンド…

require 'pty'

unless machine_file = ARGV.shift
  raise "Usage: #{$0} machine_list.txt command... "
end
command = ARGV.join(' ')

def get_pw
  system "stty -echo"
  pass = STDIN.gets
  system "stty echo"
  pass
end

pw = nil
f = open(machine_file)  rescue raise("Error: #{machine_file.to_s}, #{$!}")
machine_list = f.read.split("\n")
machine_list.each do |h|
  cmd =  "ssh -t #{h} '#{command}'"
  begin
    PTY.getpty(cmd) do  |i,o|
      o.sync = true
      line = "#{h}: "
      while (i.eof? == false)
        c = i.getc
        line << c
        if c == 0x0A
          print line
          line = "#{h}: " # 行の先頭にホスト名を表示させている。
        end
        if pw and line.index('Sorry, try again.')
          print line; line = '' # lineを初期化することにより、マッチさせないようにしている。
          pw = nil
        elsif line =~ /\[sudo\] password for.+: /
          print line; line = ''
          pw = get_pw() if pw.nil?
          o.puts pw
          o.flush
        end
      end
    end 
  rescue PTY::ChildExited # すぐにptyを作りなおすと、失敗することがある。
    retry    
  end
  # 最後の改行以降は表示していないが、必要ならここにprint lineを書くこと。
end

最新の画像もっと見る

コメントを投稿

ブログ作成者から承認されるまでコメントは反映されません。