pythonによるリモートレプリケーション(scp+expect)

2497 ワード

scp機能は強いがpasswordを手動で入力必要があり、もちろん公開鍵をリモートホストに保存する~/.sshディレクトリにはpasswordを入力必要はありませんが、構成が必要です.
sshpassではコマンドでpasswordを入力できますが、「sudo apt-get install sshpass」でインストールする必要があります.
上記の2つの方法を使用したくない場合は、expectでスクリプトを作成すると、自動的にインタラクティブになります.
pythonはpexpectモジュールも提供するが、expectが簡単である以上、なぜosを直接使用しないのか.システム()は実行しますか?
以下は私が作成したクラスで、リモート・レプリケーションを実現しました.
 
class RemoteShell:



    def __init__(self, host, user, pwd):

        self.host = host

        self.user  = user

        self.pwd  = pwd





    def put(self, local_path, remote_path):

scp_put = '''

spawn scp %s %s@%s:%s

expect "(yes/no)?" {

send "yes\r"

expect "password:"

send "%s\r"

} "password:" {send "%s\r"}

expect eof

exit'''

        os.system("echo '%s' > scp_put.cmd" % (scp_put % (os.path.expanduser(local_path), self.user, self.host, remote_path, self.pwd, self.pwd)))

        os.system('expect scp_put.cmd')

        os.system('rm scp_put.cmd')

しかし、ファイルがコピーされるたびに、expectが何をしたのかを見たいのですが、expectは-dパラメータを提供してより多くの情報を提供しています.
 
最後にコピーされたファイルが大きすぎてexpectがタイムアウトして終了したことに気づきました
スクリプトの前に「set timeout-1」を入れておけばOK
 
scp_put = '''

set timeout -1

spawn scp %s %s@%s:%s

expect "(yes/no)?" {

send "yes\r"

expect "password:"

send "%s\r"

} "password:" {send "%s\r"}

expect eof

exit'''

まとめ
 
1)expectは文ごとに順次実行される
 
 
  

  scp (yes/no)? password:, password:, , :

expect "(yes/no)?" {   send "yes\r"

                       expect "password:"

                       send "%s\r"

                    } 

       "password:" {send "%s\r"}


2)spawnのプログラムが されるたびに、expectはマッチングし、マッチングできない は、 があるのを って、タイムアウトまで のexpectを します( はexpect-dで し、 られた ).もちろんタイムアウトなし「set timeout-1」を できます
 
3)expectが すると,spawnされたプログラムがkillされる.
4)spawnが すると, のeofがexpectに され,ちょうどexpectスクリプトが するタイミングとなる.
scpではまず100% できます.scpはレプリケーションの を し、eofを します.
 
expect "100%%"

expect eof


 
 
  

5) expect ,