用python實現遠程復制 (scp + expect )


scp 功能很強大,但需要人工輸入 password, 當然可以通過把 公鑰保存在遠程主機的 ~/.ssh 目錄中,而后就不用輸入password,但這需要配置.

用 sshpass 可能在命令輸入 password, 但 需要用 “sudo apt-get install sshpass” 安裝

如果不想用上面兩種方法,可以用 expect 編寫腳本可以幫助我們自動交互

雖然 python 也提供 pexpect  模塊,但既然 expect 很簡單,為何不直接用 os.system() 去執行呢?

下面是我編寫的類,實現了遠程復制 

 

[html]  view plain copy
 
  1. class RemoteShell:  
  2.   
  3.     def __init__(self, host, user, pwd):  
  4.         self.host = host  
  5.         self.user  = user  
  6.         self.pwd  = pwd  
  7.   
  8.   
  9.     def put(self, local_path, remote_path):  
  10. scp_put = '''  
  11. spawn scp %s %s@%s:%s  
  12. expect "(yes/no)?" {  
  13. send "yes\r"  
  14. expect "password:"  
  15. send "%s\r"  
  16. } "password:" {send "%s\r"}  
  17. expect eof  
  18. exit'''  
  19.         os.system("echo '%s' > scp_put.cmd" % (scp_put % (os.path.expanduser(local_path), self.user, self.host, remote_path, self.pwd, self.pwd)))  
  20.         os.system('expect scp_put.cmd')  
  21.         os.system('rm scp_put.cmd')  


但發現每次文件都沒有復制完,我想看expect 究竟做了什么事情,還好 expect 提供 -d 參數給出更多的信息。

 

最后發現是被復制文件太大,expect 超時退出了

在腳本前加入 “set timeout -1" 就OK了

 

 

[html]  view plain copy
 
  1. scp_put = '''  
  2. set timeout -1  
  3. spawn scp %s %s@%s:%s  
  4. expect "(yes/no)?" {  
  5. send "yes\r"  
  6. expect "password:"  
  7. send "%s\r"  
  8. } "password:" {send "%s\r"}  
  9. expect eof  
  10. exit'''  


總結

 

1) expect 每一條語句都是順序執行

 

[html]  view plain copy
 
  1.   

 因為scp 可能先返回 (yes/no)? 再 返回 password:, 也可能直接返回password:, 考慮順序關系,上面語句的層次關系其實如下:

[html]  view plain copy
 
  1. expect "(yes/no)?" {   send "yes\r"  
  2.                        expect "password:"  
  3.                        send "%s\r"  
  4.                     }   
  5.        "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

 

[html]  view plain copy
 
  1. expect "100%%"  
  2. expect eof  

 

 

5) expect 是部分匹配,所以不要擔心自己不知道程序的完整輸出


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM