SSHパスワード省略について書くと,公開鍵エントリに埋もれてしまうのですが。。。
Sudoや、SSHを踏み台にしてその先のPCにRsyncするときなど、パスワード入力が毎回出てきて煩わしい.公開鍵が使えない業者のサーバーに限って,SSHで多段アクセスだったり頻繁にRsyncが必要だったりする
ruby でパスワード入力する方法
#!/usr/bin/env ruby require 'pty' require 'expect' cmd = 'rsync -avz server0:/mnt/test /home/takuya ' PTY.getpty(cmd) do | i,o | o.sync = true i.expect(/password:/,10){|line| ##入力プロンプトくるまでreadline繰り返す puts line o.puts "my_pass" o.flush } while( i.eof? == false ) puts i.gets end end
解説
pty モジュールで、疑似TTYを確保する(pty = pseudo TTY )
expect モジュールで、文字列がくるのを待つ.
以降は標準入力をEchoするだけ
pty は疑似的にターミナルを作る.つまり IOクラスが二つ(input,output)が使える
PTY.getpty(cmd) do | input_io, output_io |
PTYを確保すると,/dev/ttyにIO用にファイルが作られる(らしい)
今までに書いたExpect関連のコマンドのエントリ
Expectコマンドを使ってsu/ sudo の処理を書いてみる。 - ブックマクロ開発に
コマンドを自動化する expect - ブックマクロ開発に
RubyのNet::SSHの使い方.リモートサーバー内でsuしたりrsyncするrubyスクリプトが作れるようになる - ブックマクロ開発に
2012-07-13追加 STDIN(標準入力)から パスワードを受け取りたい。
ソースコードにパスワード直書きが精神衛生上良くない。パスワードを取り込みたい。普通に$stdin.getsすると、パスワードが丸見えになる。パスワードマスクして隠したい。
コマンドラインの文字列から、パスワードを入力するように改良した
#!/usr/bin/env ruby require 'pty' require 'expect' cmd = 'rsync -avz server0:/mnt/test /home/takuya ' PTY.getpty(cmd) do | i,o | o.sync = true i.expect(/password:/,10){|line| ##入力プロンプトくるまでreadline繰り返す puts line system "stty -echo" o.puts STDIN.gets system "stty echo" o.flush } while( i.eof? == false ) puts i.gets end end
ちなみに、rsyncの場合にSSH鍵を指定することができるので、例のrsyncの場合、秘密鍵を指定すればパスワードをexpectしなくても大丈夫
rsync -avz -e "ssh -i /home/takuya/.ssh/id_rsa -o StrictHostKeyChecking=no "
2013-03-25追記
ちなみに expect は expect コマンドをRubyのpopenで書いたものらしいです。